今人不見古時(shí)月,今月曾經(jīng)照古人
我們可以使用 java.util.concurrent.locks.Lock 來代替synchronized同步塊。它的功能更加強(qiáng)大;
Lock相對于synchronized有以下優(yōu)點(diǎn)
- Lock 可以嘗試獲取鎖 ,如果無法獲取,并不會阻塞下去而是立即返回。(嘗試獲取鎖/無阻塞獲取鎖)
- Lock 獲取鎖引發(fā)的阻塞可設(shè)置超時(shí)時(shí)間 (可超時(shí))
- Lock 獲取鎖引發(fā)的阻塞可以被中斷 (可中斷)
- Lock 支持多個相關(guān)聯(lián)的對象Condition (可以實(shí)現(xiàn)精確的喚醒) (synchronized只能隨機(jī)的喚醒一個線程[notify]或者直接喚醒全部線程[notifyAll])
- Lock 的實(shí)現(xiàn)類如ReentrantLock 可以實(shí)現(xiàn)
公平鎖,即先等待先獲取到鎖 - Lock的實(shí)現(xiàn)類如 ReadWriteLock 的讀鎖可以實(shí)現(xiàn)
并發(fā)讀
關(guān)于ReadWriteLock 可以看看這篇文章http://www.itdecent.cn/p/c2180c2ca8b7
有優(yōu)點(diǎn)就會有缺陷
Lock需要程序員顯式的加鎖和解鎖。如果lock使用不當(dāng),很可能引發(fā)死鎖或者出現(xiàn)為占有鎖而解鎖的異常;所以如何正確的使用Lock是一個非常講究的問題
那么應(yīng)該如何正確科學(xué)的使用Lock呢?可以看看我的這篇文章
http://www.itdecent.cn/p/418a9217fe51
Lock接口是實(shí)現(xiàn)類有:
ReentrantLock , ReentrantReadWriteLock.ReadLock , ReentrantReadWriteLock.WriteLock
Lock具備synchronized一樣的內(nèi)存語義
所有Lock實(shí)施必須執(zhí)行與內(nèi)置監(jiān)視器鎖相同的內(nèi)存同步語義,如The Java Language Specification (17.4 Memory Model) 所述
- 成功的
lock操作具有與成功鎖定動作相同的內(nèi)存同步效果。- 成功的
unlock操作具有與成功解鎖動作相同的內(nèi)存同步效果。- 不成功的鎖定和解鎖操作以及重入鎖定/解鎖操作,不需要任何內(nèi)存同步效果。
所謂的內(nèi)存同步效果 即是:
1、線程解鎖前,必須把工作內(nèi)存中共享變量的最新值刷新到主內(nèi)存中
2、線程加鎖時(shí),將清空工作內(nèi)存中共享變量的值,從而使用共享變量時(shí)需要從主內(nèi)存中重新獲取最新的值(注意:加鎖與解鎖需要是同一把鎖)
我們來看看這個Lock接口,它有6個方法

- 其中有4個加鎖方法:
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
- 1個解鎖方法
void unlock();
- 1個得到Condition的方法
Condition newCondition();
關(guān)于Lock接口的4個加鎖方法皆有不同
假如線程A和線程B使用同一個鎖lock,此時(shí)線程A首先獲取到鎖lock.lock(),并且始終持有不釋放。如果此時(shí)B要去獲取鎖,有四種方式:
lock.lock(): 此方式會始終處于等待中,即使調(diào)用B.interrupt()也不能中斷,除非線程A調(diào)用LOCK.unlock()釋放鎖。
lock.lockInterruptibly(): 此方式會等待,但當(dāng)調(diào)用B.interrupt()會被中斷等待,并拋出InterruptedException異常,否則會與lock()一樣始終處于等待中,直到線程A釋放鎖。 lockInterruptibly的使用看這里 http://www.itdecent.cn/p/8f5c273507b2
lock.tryLock(): 該處不會等待,獲取不到鎖并直接返回false,去執(zhí)行下面的邏輯。
lock.tryLock(10, TimeUnit.SECONDS):該處會在10秒時(shí)間內(nèi)處于等待中,當(dāng)調(diào)用B.interrupt()會被中斷等待,并拋出InterruptedException。10秒時(shí)間內(nèi)如果線程A釋放鎖,會獲取到鎖并返回true,否則10秒過后會獲取不到鎖并返回false,去執(zhí)行下面的邏輯。tryLock的詳細(xì)使用請看這里http://www.itdecent.cn/p/c42f93a86c65