[英]How to prevent deadlocks in the following C# code?
以下C#類用於多線程環境。 我刪除了很多實際的代碼。 幾乎同時調用MethodA和MethodB時會出現問題。 IsDepleted屬性中的鎖定順序不能解決問題。 從IsDepleted屬性中刪除鎖(WaitingQueue)可以解決死鎖,但是當另一個線程在WaitingQueue.Count == 0和Processing.Count == 0語句之間添加/刪除WaitingQueue中的項時,此解決方案會導致問題。
using System.Collections.Generic;
class Example
{
bool IsDepleted
{
get
{
lock (Processing)
{
lock (WaitingQueue)
{
return WaitingQueue.Count == 0
&& Processing.Count == 0;
}
}
}
}
private readonly List<object> Processing = new List<object>();
private readonly Queue<object> WaitingQueue = new Queue<object>();
public void MethodA(object item)
{
lock (WaitingQueue)
{
if (WaitingQueue.Count > 0)
{
if (StartItem(WaitingQueue.Peek()))
{
WaitingQueue.Dequeue();
}
}
}
}
public void MethodB(object identifier)
{
lock (Processing)
{
Processing.Remove(identifier);
if (!IsDepleted)
{
return;
}
}
//Do something...
}
bool StartItem(object item)
{
//Do something and return a value
}
}
獲取方法A中的Processing鎖定和方法B中的WaitingQueue鎖定(換句話說,使其看起來像第一個代碼塊)。 這樣,你總是以相同的順序拿鎖,你永遠不會死鎖。
這取決於您是否需要快速修復或嚴格修復。
快速修復只是在所有情況下使用一個鎖定對象。
例如private readonly object _lock = new object();
然后鎖定它。 但是,根據您的情況,這可能會影響性能,超出您的接受程度。
即你的代碼將成為這樣:
using System.Collections.Generic;
class Example
{
private readonly object _lock = new object();
bool IsDepleted
{
get
{
lock (_lock)
{
return WaitingQueue.Count == 0
&& Processing.Count == 0;
}
}
}
private readonly List<object> Processing = new List<object>();
private readonly Queue<object> WaitingQueue = new Queue<object>();
public void MethodA(object item)
{
lock (_lock)
{
if (WaitingQueue.Count > 0)
{
if (StartItem(WaitingQueue.Peek()))
{
WaitingQueue.Dequeue();
}
}
}
}
public void MethodB(object identifier)
{
lock (_lock)
{
Processing.Remove(identifier);
if (!IsDepleted)
{
return;
}
}
//Do something...
}
bool StartItem(object item)
{
//Do something and return a value
}
}
簡化代碼並僅使用單個對象鎖定。 你也可以用以下方法替換你的鎖:
Monitor.TryEnter(處理中,1000)
這將給你1秒的超時。 基本上:
if (Monitor.TryEnter(Processing, 1000))
{
try
{
//do x
}
finally
{
Monitor.Exit(Processing);
}
}
現在你不會停止死鎖,但你可以處理你沒有鎖定的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.