ReentrantLock
1.什么是ReentrantLock
1.1ReentrantLock 與Synchronized區別
在面試中詢問ReentrantLock與Synchronized區別時,一般回答都是
ReentrantLock
- ReentrantLock是JDK方法,需要手動聲明上鎖和釋放鎖,因此語法相對復雜些;如果忘記釋放鎖容易導致死鎖
- ReentrantLock具有更好的細粒度,可以在ReentrantLock里面設置內部Condititon類,可以實現分組喚醒需要喚醒的線程
- RenentrantLock能實現公平鎖
Synchronized
- Synchoronized語法上簡潔方便
- Synchoronized是JVM方法,由編輯器保證枷鎖和釋放
構造方法
public class ReentrantLock implements Lock, java.io.Serializable { public ReentrantLock() { sync = new NonfairSync(); } /** * Creates an instance of {@code ReentrantLock} with the * given fairness policy. * * @param fair {@code true} if this lock should use a fair ordering policy */ public ReentrantLock(boolean fair) { sync = fair ? new FairSync() : new NonfairSync(); } }
ReentrantLock有兩個構造方法,一個是無參的 ReentrantLock() ;另一個含有布爾參數public ReentrantLock(boolean fair)。后面一個構造函數說明ReentrantLock可以新建公平鎖;而Synchronized只能建立非公平鎖。
(公平鎖:公平鎖,是按照通過CLH等待線程按照先來先得的規則,公平的獲取鎖;而非公平鎖,則當線程要獲取鎖時,它會無視CLH等待隊列而直接獲取鎖
轉裝於:https://www.cnblogs.com/kexianting/p/8550975.html
)
Lock中的newCondition方法
public Condition newCondition() { return sync.newCondition(); }
Condition詳解:https://www.cnblogs.com/gemine/p/9039012.html 與Object的wait與notify用法類似。
獲取鎖的方式
void lock()獲取鎖。
void lockInterruptibly()如果當前線程未被中斷,則獲取鎖。
boolean tryLock() 僅在調用時鎖未被另一個線程保持的情況下,才獲取該鎖。
boolean tryLock(long timeout, TimeUnit unit) timeout:時間long值如10L TimeUnit 時間單位如TimeUnit.SECONDS 代表等待10秒若未獲取到鎖則放棄。
public class MyLock implements Runnable { int i =10; int num = 100; boolean flag = true; ReentrantLock l = new ReentrantLock(true); public void run() { while (i >= 1) { //加鎖 //如果當前獲取不到鎖則返回false 不等待繼續執行下面 if (l.tryLock()) { try { flag=false; Thread.sleep(500); //睡眠一會 if (i > 0) { System.out.println(Thread.currentThread().getName() + "正在售賣:" + (i--) + "張票"); } } catch (InterruptedException e) { // e.printStackTrace(); } finally { flag=true; l.unlock(); } }
if(flag&&num>0)
{
int i = 5;
// System.out.println(Thread.currentThread().getName());
for (int r = 0 ;r<10;r++){
try {
Thread.sleep(900);
} catch (InterruptedException e) {
e.printStackTrace();
}
// if(i>0)
System.out.println(i--+""+Thread.currentThread().getName());
}
i=5;
}
} }
得出結論:當線程沒拿到鎖后,會開始執行下面的代碼,且當執行完之后才會繼續去嘗試獲取鎖
如果鎖在給定等待時間內沒有被另一個線程保持,且當前線程未被中斷,則獲取該鎖。
void unlock()釋放鎖,建議放在finally中 避免出現異常導致死鎖的發生。
https://www.cnblogs.com/kkxwze/p/11168525.html
