“嗨,阿米戈!”
“今天我要告訴你什麼是死鎖。”
“嘿,你已經和我說過類似的事情了。”
“是的,我做到了。但今天我們將更詳細地考慮這個話題。”
“在最簡單的情況下,死鎖涉及兩個線程和兩個互斥對象。互鎖發生在:”
A)每個線程都需要獲取兩個互斥量。
B) 第一個線程已經獲取了第一個互斥鎖,正在等待第二個互斥鎖被釋放。
C) 第二個線程獲得了第二個互斥體,正在等待第一個互斥體被釋放。
“這裡有些例子:
例子
public class Student
{
private ArrayList friends = new ArrayList();
public synchronized ArrayList getFriends()
{
synchronized(friends)
{
return new ArrayList(friends);
}
}
public synchronized int getFriendsCount()
{
return friends.size();
}
public int addFriend(Student student)
{
synchronized(friends)
{
friends.add(student)
return getFriendsCount ();
}
}
}
“假設一個線程調用getFriends方法,獲取this對象的互斥量,然後獲取friends對象的互斥量。”
“與此同時,第二個線程調用addFriend方法,獲取好友對象的互斥量,然後獲取此對象的互斥量(在調用getFriendsCount期間)。”
“起初,一切都會好起來的,但正如墨菲定律所說:任何可能出錯的事情都會出錯。不可避免地會出現第一個線程只有時間獲取一個互斥鎖,而第二個線程將獲取第二個互斥鎖的情況就在那一刻互斥鎖。它們會像那樣掛起,永遠等待另一個線程釋放互斥鎖。”
“我決定引用我在書中找到的另一個簡單例子:”
例子
class KnightUtil
{
public static void kill(Knight knight1, Knight knight2)
{
synchronized(knight1)
{
synchronized(knight2)
{
knight2.live = 0;
knight1.experience += 100;
}
}
}
}
”有一個遊戲,兩個騎士在打架。一個騎士殺死了另一個。這種行為體現在 kill方法中。將兩個騎士對像傳遞給它。
“首先,我們保護這兩個對象,這樣其他人就無法更改它們。”
“第二個騎士死了(HP = 0)”
“第一個騎士獲得 100 XP。”
“一切似乎都很好,但可能會出現第二個騎士同時攻擊第一個騎士的情況。第二個騎士也調用了這種方法,但騎士對象的傳遞順序不同。”
“你的意思是我們甚至不需要多種方法來陷入僵局?”
“是的。有時只需要一種簡單的方法就會導致線程和整個程序掛起。”
“是啊,我想這種現像比我想像的更頻繁發生。謝謝,艾莉。”
GO TO FULL VERSION