有人可以向我解釋Reentrant lock
和deadlock
與Java代碼(僞)例子的相互關係嗎?Java中的可重入鎖定和死鎖
7
A
回答
11
一個可重入的鎖定機制允許持有鎖的線程重新進入關鍵部分。這意味着你可以做這樣的事情:
public synchronized void functionOne() {
// do something
functionTwo();
// do something else
// redundant, but permitted...
synchronized(this) {
// do more stuff
}
}
public synchronized void functionTwo() {
// do even more stuff!
}
在非重入鎖,你將有一個死鎖的情況,當你嘗試調用functionTwo()
從functionOne()
因爲線程必須等待鎖..它自己擁有。
死鎖當然是線程1持有鎖A並等待鎖B而線程2持有鎖B並等待鎖A的惡劣情況。因此,兩者都不能繼續。此代碼示例創建了一個僵局:
public synchronized void deadlock() throws InterruptedException {
Thread th = new Thread() {
public void run() {
deadlock();
}
}.start();
th.join();
}
調用線程試圖等待各地的產生的線程,這又不能打電話deadlock()
直到呼叫方已退出。嘉潮!
0
即使通過輸入其他代碼塊已經獲得鎖定,可重入鎖定仍將允許鎖定持有者輸入代碼塊。一個不可重入的鎖會讓鎖持有者自己鎖定,因爲它必須釋放從另一個代碼塊獲得的鎖以重新獲得同一個鎖以進入需要代碼塊的嵌套鎖。就死鎖而言,如果您從受保護的代碼塊中調用受保護的代碼塊,您將需要一個可重入的鎖(或者在等待自己時您會死鎖)。
1
這裏的僵局與ReentrantLock的
class Deadlock {
private static final ReentrantLock l1 = new ReentrantLock();
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("A Trying to lock...");
l1.lock();
System.out.println("A Locked...");
try {
Thread t = new Thread(new Runnable() {
public void run() {
System.out.println("B Trying to lock...");
l1.lock();
System.out.println("B Must not print");
try {
} finally {
System.out.println("B Trying to unlock...");
l1.unlock();
System.out.println("B Unlocked...");
}
}
});
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
} finally {
System.out.println("A Trying to unlock...");
l1.unlock();
System.out.println("A Unlocked...");
}
}
});
t.start();
}
}
一個例子來解決僵局,調用註釋掉t.join
,與封閉的try/catch一起。
6
死鎖發生,然後線程等待一個永遠不會發生的情況。
顯而易見的情況是,當您試圖鎖定兩個鎖時,按不同的線程以不同的順序鎖定。
ReentrantLock lock1 = new ReentrantLock();
ReentrantLock lock2 = new ReentrantLock();
public void methodA() {
lock1.lock();
lock2.lock();
// do something and un lock both.
}
public void methodB() {
lock2.lock();
lock1.lock();
// do something and un lock both.
}
正如你可以看到它是可能的線程調用了methodA並獲得鎖1等待鎖2,和另一個線程調用的methodB並獲得鎖2等待鎖1。
但是,它可能導致線程自身死鎖。一個示例是ReentrantReadWriteLock,因爲它不支持將讀鎖升級到寫鎖。
ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
rwl.readLock().lock();
// do we need to update?
rwl.writeLock().lock(); // will wait for the readLock() to be released!
一個不起眼的機會死鎖自己是在暗示鎖使用。所以鎖用於即使靜態初始化器塊不
class A {
private static int VALUE;
static {
Thread t = new Thread() {
public void run() {
// waits for the A class to load.
VALUE = someLongTask();
}
};
t.start();
// waits for the thread.
t.join();
}
}
同樣,你有一個僵局靜態初始化器塊隱含線程安全的!
相關問題
- 1. 正確的鎖定/解鎖使用Java的可重入鎖
- 2. 可重入鎖定
- 3. Java ExecuterService死鎖?
- 4. Python線程和鎖定:死鎖
- 5. Postgresql鎖死鎖
- 6. 可重入鎖定問題
- 7. pthread_mutex_timedlock和死鎖
- 8. Quartz.NET和死鎖
- 9. Restkit和死鎖
- 10. Java,線程死鎖?
- 11. Java死鎖問題
- 12. Java線程死鎖
- 13. ActiveRecord3死鎖重試
- 14. 在SQL中使用雙重檢查鎖定的死鎖
- 15. MySQL返回死鎖插入行和FK被鎖定'更新'
- 16. 帶鎖的單身人士 - 可能的死鎖?在java
- 17. 鎖分區死鎖
- 18. 死鎖鎖()方法
- 19. java中的LinkedBlockingQueue和寫入鎖定
- 20. MS SQL Server中的IsolationLevel,鎖定模式,死鎖和sp_getapplock
- 21. Java:奇怪的死鎖
- 22. 死鎖的線程java
- 23. Java的新手 - 死鎖仿
- 24. 帶鎖的死鎖工作
- 25. 強制解鎖一個可重入鎖
- 26. 了TerminateProcess和死鎖
- 27. 死鎖SQLServer中
- 28. Java的:爲什麼這是一個死鎖時鎖定爲空?
- 29. 死鎖
- 30. TAO在鎖定時發生死鎖
我猜OP意味着使用類java.util.concurrent.locks.ReentrantLock而不是'synchronized'塊的例子。 –
@Victor Sorokin我不確定他是否適合大寫字母。不管是使用'synchronized'塊還是'ReentrantLock'類,高級概念都是完全相同的。 – stevevls