目錄
ReentrantLock使用示例lock.lockInterruptibly();
有了synchronized爲什麼還要Lock
Synchronized | ReentrantLock | |
類型 | 關鍵字:修飾方法或者代碼塊 | 接口:常用的五個方法 |
隱式獲取鎖,把鎖的獲取和釋放固化了,即先獲取再釋放 |
1、能夠嘗試非阻塞獲取鎖(tryLock()) 2、能夠響應中斷,被中斷時,會跑出中斷異常,同時會釋放鎖 3、能夠超時獲取鎖tryLock(long time, TimeUnit unit) |
|
可重入(原理:線程持有者和計數器) | 支持 | 已經獲取到鎖的線程,能夠再次調用lock()方法獲取鎖而不被阻塞 |
公平:先對鎖獲取的先被滿足,效率低 非公平:多個線程不管先後競爭鎖 |
非公平 | 通過構造函數自定義public ReentrantLock(boolean fair) |
lock常用的方法
方法名稱 | 描述 |
void lock(); | 獲取鎖,調用該方法當前線程會獲取鎖,當獲取鎖後,從該方法返回 |
void lockInterruptibly() throws InterruptedException; | 可中斷地獲取鎖,和lock()方法的不同之處在於該方法會響應中斷,即在鎖的獲取中可以中斷當前線程 |
boolean tryLock(); | 嘗試獲取鎖,調用後回立即返回,獲取到鎖true,否則返回fasle |
boolean tryLock(long time, TimeUnit unit) throws InterruptedException; |
1、在超時時間獲取鎖:true 2、在超時時間內被中斷:false 3、超時:false |
void unlock(); | 釋放鎖 |
lock使用的標準代碼
lock.lock();
try{
count++;
}finally{
lock.unLock();
}
ReentrantLock使用示例lock和unlock:
兩個線程對count自增1000,另一個線程對count自減1000
public class MyReentrantLock {
int count = 1000;
public static void main(String[] args) throws InterruptedException {
MyReentrantLock myReentrantLock = new MyReentrantLock();
Lock lock = new ReentrantLock();
new Thread(() -> {
for (int i = 0; i < 10000; i++) {
lock.lock();
try {
myReentrantLock.count++;
} finally {
lock.unlock();
}
}
}).start();
new Thread(() -> {
for (int i = 0; i < 10000; i++) {
lock.lock();
try {
myReentrantLock.count--;
} finally {
lock.unlock();
}
}
}).start();
//主線程一定要進行休眠,否則可能會得到修改過程中count的值,而不是最終值
Thread.sleep(1000);
System.out.println(myReentrantLock.count);
}
}
結果:1000
ReentrantLock使用示例tryLock()
public static void main(String[] args) throws InterruptedException {
MyReentrantLock myReentrantLock = new MyReentrantLock();
Lock lock = new ReentrantLock();
Thread thread = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
if (lock.tryLock(500, TimeUnit.MILLISECONDS)) {
Thread.sleep(100);
myReentrantLock.count++;
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
thread.start();
//thread.interrupt();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
if (lock.tryLock()) {
try {
myReentrantLock.count--;
} finally {
lock.unlock();
}
}
}
});
//thread2.interrupt();
//主線程一定要進行休眠,否則可能會得到修改過程中count的值,而不是最終值
Thread.sleep(1000);
System.out.println(myReentrantLock.count);
}
}
結果在:1000-1010之間
ReentrantLock使用示例lock.lockInterruptibly();
public class MyReentrantLock {
int count = 1000;
public static void main(String[] args) throws InterruptedException {
MyReentrantLock myReentrantLock = new MyReentrantLock();
Lock lock = new ReentrantLock();
Thread thread2 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
lock.lockInterruptibly();
Thread.sleep(100);
myReentrantLock.count--;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
});
thread2.start();
Thread.sleep(100);
thread2.interrupt();
//主線程一定要進行休眠,否則可能會得到修改過程中count的值,而不是最終值
Thread.sleep(1200);
System.out.println(myReentrantLock.count);
}
}
結果:
java.lang.InterruptedException
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireInterruptibly(AbstractQueuedSynchronizer.java:1220)
at java.util.concurrent.locks.ReentrantLock.lockInterruptibly(ReentrantLock.java:335)
at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:39)
at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261)
at java.util.concurrent.locks.ReentrantLock.unlock(ReentrantLock.java:457)
at cn.enjoyedu.ch4.MyReentrantLock.lambda$main$0(MyReentrantLock.java:45)
at java.lang.Thread.run(Thread.java:748)
999