3 回答

TA貢獻(xiàn)1810條經(jīng)驗(yàn) 獲得超4個(gè)贊
同步有兩個(gè)主要用例:資源訪問和事件傳遞。您試圖解決的并發(fā)問題需要事件傳遞:第二個(gè)線程等待第一個(gè)線程的信號(hào),第三個(gè)線程等待第二個(gè)線程的信號(hào)。信號(hào),我的意思是,是空事件,它們帶有事件已經(jīng)發(fā)生的事實(shí),沒有任何額外的細(xì)節(jié)。
Semaphore
s 非常適合信號(hào)傳遞(盡管也可用于資源訪問)。ReentrantLock
s 是為資源訪問而設(shè)計(jì)的。從技術(shù)上講,任何事件傳遞機(jī)制都是建立在資源訪問之上的。因此您可以使用ReentrantLock
s 進(jìn)行信號(hào)傳遞,但它需要一些額外的編程(在@billie 的回答中演示)。

TA貢獻(xiàn)2011條經(jīng)驗(yàn) 獲得超2個(gè)贊
正如您所發(fā)現(xiàn)的,信號(hào)量易于實(shí)現(xiàn)和推理 - 獲取鎖定、執(zhí)行操作、釋放鎖定。ReentrantLocks 是不同的,旨在服務(wù)于您發(fā)布的示例中不存在的更復(fù)雜的目的。是的,ReentrantLocks 由單個(gè)線程擁有,只能由該線程釋放。
如果您的目標(biāo)是生成供兩個(gè)線程使用的受保護(hù)代碼,則使用信號(hào)量會(huì)比 ReentrantLock 更簡單且更不容易出錯(cuò)。但是,如果您的目標(biāo)是了解 ReentrantLocks 的工作原理(或者如果您的用例以某種方式更適合 ReentrantLocks 而不是從上面的示例中清楚地看到),我鼓勵(lì)您閱讀 Javadoc - https://docs.oracle.com/ javase/7/docs/api/java/util/concurrent/locks/ReentrantLock.html - 它包含有關(guān)如何使用它們以及它們的行為方式的有用信息。

TA貢獻(xiàn)1815條經(jīng)驗(yàn) 獲得超6個(gè)贊
ReentrantLock解鎖狀態(tài)的API將拋出IllegalMonitorStateException - if the current thread does not hold this lock,在您的代碼中,這看起來正是正在發(fā)生的事情。
這不是ReentrantLocks 的正常用法,但是如果您無論如何都想使用它們來完成此操作,那么一種方法可能是使用以下方法跟蹤狀態(tài):
private volatile int tracker = 0;
private Lock lock= new ReentrantLock();
public void first(Runnable printFirst) throws InterruptedException {
lock.lock();
try {
printFirst.run();
tracker++;
} finally {
lock.unlock();
}
}
public void second(Runnable printSecond) throws InterruptedException {
while(!Thread.currentThread().isInterrupted()) {
lock.lock();
try {
if (tracker == 1) {
printSecond.run();
tracker++;
break;
}
} finally {
lock.unlock();
}
Thread.yield();
}
}
public void third(Runnable printThird) throws InterruptedException {
while(!Thread.currentThread().isInterrupted()) {
lock.lock();
try {
if (tracker == 2) {
printThird.run();
tracker++;
break;
}
} finally {
lock.unlock();
}
Thread.yield();
}
}
如果您希望它更高效(減少第二個(gè)/第三個(gè)函數(shù)的處理),那么您可能需要查看類似Condition https://docs.oracle.com/javase/7/docs/api/java/util/concurrent的內(nèi)容/鎖/Condition.html
作為旁注,您可以通過為每個(gè)操作要求/釋放多個(gè)許可來僅使用一個(gè)信號(hào)量來完成此操作。
添加回答
舉報(bào)