避免Java多線程中死鎖情況的策略之一是使用超時。 假設一個線程獲得了一個資源的鎖定,現在正在等待另一個資源的鎖定。經過一段時間後,如果它無法獲取resource2上的鎖定,那麼它應該停止等待resource2上的鎖定。它也應該釋放resource1上的鎖。因此可以避免死鎖。使用超時避免Java多線程中的死鎖
但是如何在Java中實現它?如何顯式「釋放」鎖?如何定義超時等待鎖定。
什麼是確切的java命令和語法。請問任何你好世界的例子?
避免Java多線程中死鎖情況的策略之一是使用超時。 假設一個線程獲得了一個資源的鎖定,現在正在等待另一個資源的鎖定。經過一段時間後,如果它無法獲取resource2上的鎖定,那麼它應該停止等待resource2上的鎖定。它也應該釋放resource1上的鎖。因此可以避免死鎖。使用超時避免Java多線程中的死鎖
但是如何在Java中實現它?如何顯式「釋放」鎖?如何定義超時等待鎖定。
什麼是確切的java命令和語法。請問任何你好世界的例子?
這裏是2個鎖和2個線程試圖獲取他們以不同的順序一個人爲的例子。沒有超時,代碼就會死鎖。
public static void main(String[] args) throws Exception {
final ReentrantLock lock1 = new ReentrantLock();
final ReentrantLock lock2 = new ReentrantLock();
Runnable try1_2 = getRunnable(lock1, "lock 1", lock2, "lock 2");
Runnable try2_1 = getRunnable(lock2, "lock 2", lock1, "lock 1");
new Thread(try1_2).start();
new Thread(try2_1).start();
}
private static Runnable getRunnable(final ReentrantLock lock1, final String lock1Name, final ReentrantLock lock2, final String lock2Name) {
return new Runnable() {
@Override
public void run() {
try {
if (lock1.tryLock(1, TimeUnit.SECONDS)) {
System.out.println(lock1Name + " acquired in thread " + Thread.currentThread());
if (lock2.tryLock(1, TimeUnit.SECONDS)) {
System.out.println(lock2Name + " acquired in thread " + Thread.currentThread());
Thread.sleep(2000);
} else {
System.out.println("Could not acquire "+lock2Name + " in thread " + Thread.currentThread());
lock1.unlock();
System.out.println(lock1Name + " released in thread " + Thread.currentThread());
}
} else {
System.out.println("Could not acquire " + lock1Name + " in thread " + Thread.currentThread());
}
} catch (InterruptedException e) {
//you should not ignore it
} finally {
if (lock1.isHeldByCurrentThread()) lock1.unlock();
if (lock2.isHeldByCurrentThread()) lock2.unlock();
}
}
};
}
從Java併發實踐中的例子! ;) –
@assylias當調用對象的同步方法時,線程會自動嘗試獲取「鎖定該對象」。而在使用「java.util.concurrent.locks.Lock」時,我們不會請求「鎖定對象的對象」,我們正在調用其方法。所以我認爲,要正確使用「鎖定」類,我們不應將方法標記爲同步。但是我們應該有一個與該對象關聯的「Lock」實例。在調用代碼之前(需要同步),我們應該在相關的鎖上嘗試tryLock()。 ---- Plz繼續閱讀下面的評論------ –
@assylias 所以我們沒有物理鎖定我們調用的方法的對象,但邏輯上鎖定。 就像我們在每個對象上都有一塊黑板,在調用方法之前,我們只是在blackbord上寫上「嘿,我已經鎖定了!」 。我們實際上並沒有鎖定對象。 其他線程會檢查黑板,看看有人說「他已鎖定」。所以它不會繼續。 對嗎? –
Use tryLock(timeout, timeunits);
獲取鎖,如果它是在給定內免費等待時間和 當前線程未被中斷。如果鎖可用,則此 方法立即返回立即,值爲
true
。如果鎖不 可用,那麼當前線程用於線程 調度目的禁用並一直處於休眠狀態的三種情況之一 情況:
的鎖收購由當前線程;
或其他某個線程 中斷當前線程,和鎖獲取的中斷 支撐;
或指定的等待時間
可能這種幫助,
Lock lock = null;
lock=....;
if (lock.tryLock(15L, TimeUnit.SECONDS)) {
try {
........
} finally {
lock.unlock();
}
} else {
// do sumthing
}
在Java 8+ Concurrency API你可以設置一個明確的時間爲lock
等待時,它的條件設定爲:
private Lock lock = new ReentrantLock();
private Condition myCondition = lock.newCondition();
try{
myCondition.await(1200L, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
System.out.println((e);
} finally{
lock.unlock();
}
鎖定將等待,直到它收到一個signal()
或signalAll()
從另一個線程或直到1.2秒的時間到期。
其他解決方案;總是以相同的順序獲得鎖,或永遠不會獲得多個鎖。 ;) –
+1爲'如何定義超時等待鎖' – n611x007