可重入锁 不可重入锁_什么是可重入锁?
可重入鎖 不可重入鎖
在Java 5.0中,增加了一個(gè)新功能以增強(qiáng)內(nèi)部鎖定功能,稱為可重入鎖定。 在此之前,“同步”和“易失性”是實(shí)現(xiàn)并發(fā)的手段。
同步使用固有鎖或監(jiān)視器。 Java中的每個(gè)對(duì)象都有一個(gè)與之關(guān)聯(lián)的固有鎖。 每當(dāng)線程嘗試訪問(wèn)同步的塊或方法時(shí),它都會(huì)獲取該對(duì)象的固有鎖定或監(jiān)視器。 在使用靜態(tài)方法的情況下,線程獲取對(duì)類對(duì)象的鎖定。
就代碼編寫而言,內(nèi)在鎖定機(jī)制是一種干凈的方法,對(duì)于大多數(shù)用例而言,它都是不錯(cuò)的選擇。 那么,為什么我們需要顯式鎖的其他功能? 讓我們討論。
內(nèi)部鎖定機(jī)制可能具有一些功能限制,例如:
除此之外,ReentrantLock還支持鎖輪詢和支持超時(shí)的可中斷鎖等待。 ReentrantLock還支持可配置的公平性策略,從而允許更靈活的線程調(diào)度。
讓我們看一下ReentrantLock類(實(shí)現(xiàn)Lock)實(shí)現(xiàn)的幾種方法:
void lock();void lockInterruptibly() throws InterruptedException;boolean tryLock();boolean tryLock(long time, TimeUnit unit) throws InterruptedException; .....讓我們嘗試了解這些用法,看看我們可以得到什么好處。
讓我們看一下示例代碼:
public void transferMoneyWithSync(Account fromAccount, Account toAccount,float amount) throws InsufficientAmountException {synchronized (fromAccount) {// acquired lock on fromAccount Objectsynchronized (toAccount) {// acquired lock on toAccount Objectif (amount > fromAccount.getCurrentAmount()) {throw new InsufficientAmountException("Insufficient Balance");} else {fromAccount.debit(amount);toAccount.credit(amount);}}}}在上面的transferMoney()方法中,當(dāng)2個(gè)線程A和B幾乎同時(shí)嘗試轉(zhuǎn)移資金時(shí),可能會(huì)出現(xiàn)死鎖。
A: transferMoney(acc1, acc2, 20); B: transferMoney(acc2, acc1 ,25);線程A可能已獲得對(duì)acc1對(duì)象的鎖定,并正在等待獲取對(duì)acc2對(duì)象的鎖定,同時(shí)線程B已獲得了對(duì)acc2對(duì)象的鎖定,并且正在等待對(duì)acc1的鎖定。 這將導(dǎo)致死鎖,并且必須重新啟動(dòng)系統(tǒng)!
但是,有一種避免這種情況的方法,也就是所謂的“鎖定排序”,我個(gè)人認(rèn)為這有點(diǎn)復(fù)雜。
ReentrantLock使用tryLock()方法實(shí)現(xiàn)了一種更干凈的方法。 這種方法稱為“定時(shí)和輪詢鎖定獲取”。 如果您無(wú)法獲取所有必需的鎖,釋放已獲取的鎖并重試,它可以讓您重新獲得控制權(quán)。
因此,使用tryLock我們將嘗試獲取兩個(gè)鎖,如果無(wú)法同時(shí)獲取這兩個(gè)鎖,則如果已經(jīng)獲取了其中之一,則釋放它,然后重試。
public boolean transferMoneyWithTryLock(Account fromAccount,Account toAccount, float amount) throws InsufficientAmountException, InterruptedException {// we are defining a stopTimelong stopTime = System.nanoTime() + 5000;while (true) {if (fromAccount.lock.tryLock()) {try {if (toAccount.lock.tryLock()) {try {if (amount > fromAccount.getCurrentAmount()) {throw new InsufficientAmountException("Insufficient Balance");} else {fromAccount.debit(amount);toAccount.credit(amount);}} finally {toAccount.lock.unlock();}}} finally {fromAccount.lock.unlock();}}if(System.nanoTime() < stopTime)return false;Thread.sleep(100);}//while}在這里,我們實(shí)現(xiàn)了定時(shí)鎖,因此,如果在指定時(shí)間內(nèi)無(wú)法獲取鎖,則transferMoney方法將返回失敗通知并正常退出。
我們還可以使用此概念來(lái)維護(hù)時(shí)間預(yù)算活動(dòng)。
可中斷的鎖獲取允許在可取消的活動(dòng)中使用鎖。
lockInterruptible方法使我們能夠嘗試獲取鎖,但可用于中斷。 所以基本上這意味著 它允許線程立即響應(yīng)從另一個(gè)線程發(fā)送給它的中斷信號(hào)。
當(dāng)我們要向所有等待的鎖發(fā)送KILL信號(hào)時(shí),這將很有幫助。
讓我們看一個(gè)例子,假設(shè)我們有一條共享的行來(lái)發(fā)送消息,我們希望以這樣的方式設(shè)計(jì)它:如果另一個(gè)線程來(lái)了并且中斷了當(dāng)前線程,則應(yīng)該釋放鎖并執(zhí)行退出或關(guān)閉操作以取消當(dāng)前任務(wù)。
public boolean sendOnSharedLine(String message) throws InterruptedException{lock.lockInterruptibly();try{return cancellableSendOnSharedLine(message);} finally {lock.unlock();}}private boolean cancellableSendOnSharedLine(String message){ .......定時(shí)tryLock也可響應(yīng)中斷。
在固有鎖中,獲取釋放對(duì)是塊結(jié)構(gòu)的,即,無(wú)論控制如何退出該塊,始終在獲取該鎖的同一基本塊中釋放該鎖。
外在鎖提供了進(jìn)行更明確控制的功能。
使用外部鎖可以更輕松地實(shí)現(xiàn)某些概念,例如“鎖緊皮帶”。 在哈希混和集合和鏈接列表中可以看到一些用例。
ReentrantLock構(gòu)造函數(shù)提供兩個(gè)公平選項(xiàng)的選擇:創(chuàng)建非公平鎖或公平鎖。 公平鎖的線程只能在它們所要求的順序獲取鎖,而一個(gè)不公平的鎖允許鎖獲取它反過(guò)來(lái)的,這就是所謂的駁運(yùn) (打破了隊(duì)列和獲取鎖,當(dāng)它變得可用)。
由于掛起和恢復(fù)線程的開銷,公平鎖定會(huì)帶來(lái)巨大的性能成本。 在某些情況下,恢復(fù)掛起的線程與實(shí)際運(yùn)行之間會(huì)有明顯的延遲。 讓我們看一下情況:
A -> holds lock B -> has requested and is in suspended state waiting for A to release lock C -> requests the lock at the same time when A releases the lock, C has not yet gone to suspended state.由于C尚未處于掛起狀態(tài),因此它有可能獲得A釋放的鎖,使用它,然后在B甚至還沒(méi)有喚醒之前釋放它。 因此,在這種情況下,不公平鎖定具有明顯的性能優(yōu)勢(shì)。
內(nèi)部鎖和外部鎖在內(nèi)部具有相同的鎖定機(jī)制,因此性能的提高純粹是主觀的。 這取決于我們上面討論的用例。 外在鎖提供了更明確的控制機(jī)制,可以更好地處理死鎖,饑餓等。我們將在以后的博客中看到更多示例。
翻譯自: https://www.javacodegeeks.com/2013/11/what-are-reentrant-locks.html
可重入鎖 不可重入鎖
總結(jié)
以上是生活随笔為你收集整理的可重入锁 不可重入锁_什么是可重入锁?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 用户身份验证最佳做法清单
- 下一篇: 使用Amazon s3托管您的Maven