在JDK1.5后,并發包里新增了Lock接口以及其實現類來實現鎖功能,它提供了與synchronized關鍵字類似的鎖功能,但它需要手動開啟、關閉鎖。雖然看起來沒有synchronized方便,但它可以支持鎖的可操作性,可中斷獲取,超時獲取等多種非常使用的同步機制,下面主要圍繞重入鎖、讀寫鎖展開
1、Lock接口的api
1、void lock()獲取鎖,調用該方法當前線程獲取鎖,獲取鎖之后返回
2、void lockInterruptibly() throws interruptedException可中斷獲取鎖,與lock方法不同在于該方法可影響中斷,既在鎖的獲取過程中可中斷當前線程
3、boolean tryLock()嘗試非阻塞獲取鎖,調用方法立即返回,返回true為成功
4、boolean tryLock(long time,TimeUnit unit) throws interruptedException 超時獲取鎖,一下情況會返回:時間內獲取到了鎖、時間內被中斷、時間到了沒有獲取鎖
5、void unLock()釋放鎖
2、ReentrantLock重入鎖(排它鎖)
它支持重進入的鎖,即該鎖支持同一個線程對共享資源重復進入加鎖,還支持獲取鎖的公平、非公平的選擇(在絕對時間上,先對鎖進行索取的請求一定先被滿足,那么這個鎖就是公平的,反之就是不公平的。非公平鎖效率高于公平鎖,ReentrantLock默認是非公平鎖)
應用場景如下:
1、如果發現該操作已經在執行中則不再執行(有狀態執行)
如定時任務發現前一個尚未執行完,則本次直接返回不再執行
private ReentrantLock lock=new ReentrantLock();
if(lock.tryLock()){//如果已經被占用則直接返回false不會等待,達到忽略操作的效果
try{}finally{
lock.unLock();
}
}
2、如果發現有在執行的,那么等待一個一個執行
ReentrantLock lock=new ReentrantLock();//非公平鎖,默認為false
ReentrantLock lock=new ReentrantLock(true);//公平鎖,跟synchronized一致
try{
lock.lock();//如果鎖被占用那么會等待,直到鎖被釋放
}finally{
lock.unLock();
}
3、如果發現有鎖被占用,那么則等待指定時間,如果等待超時則不執行
可有效防止一致等待導致死鎖
try{
if(lock.tryLock(5,TimeUnit.SECONDS)){//發現被占用則最大等待5秒,5秒內執行完可占用該鎖,執行不完返回false
try{}finally{
lock.unLock();
}
}
}catch(InterruptedException e){}
4、如果發現被占用,則可中斷正在進行的操作,釋放該鎖繼續下一個操作
可有效防止鎖被長時間占用,對資源的長時間消耗
try{
lock.lockInterruptibly();
}catch(InterruptedException e)finally{
lock.unLock();
}
3、ReentrantReadWriteLock(讀寫鎖,共享鎖)
排他鎖:讀寫互斥、讀讀互斥、寫寫互斥
共享鎖:讀讀共享、讀寫互斥、寫寫互斥
JDK1.5讀寫可能出現死鎖,建議1.6以上
浙公網安備 33010602011771號