通常,當我想一類是線程安全的,我這樣做如下:這是一個很好的設計在C#中創建線程安全類?
public class ThreadSafeClass
{
private readonly object theLock = new object();
private double propertyA;
public double PropertyA
{
get
{
lock (theLock)
{
return propertyA;
}
}
set
{
lock (theLock)
{
propertyA = value;
}
}
}
private double propertyB;
public double PropertyB
{
get
{
lock (theLock)
{
return propertyB;
}
}
set
{
lock (theLock)
{
propertyB = value;
}
}
}
public void SomeMethod()
{
lock (theLock)
{
PropertyA = 2.0 * PropertyB;
}
}
}
它的工作原理,但它是非常冗長。有時我甚至會爲每種方法和屬性創建一個鎖對象,以創建更多的冗長和複雜性。
我知道也可以使用Synchronization屬性來鎖定類,但我不確定這個比例有多好 - 因爲我經常期望有數十萬甚至數百萬個線程安全實例對象。這種方法會爲類的每個實例創建一個同步上下文,並且要求該類從ContextBoundObject派生,因此不能從其他任何派生出來 - 因爲C#不允許多繼承 - 這是一個顯示限制器在許多情況下。
編輯:正如幾位響應者所強調的那樣,沒有「銀彈」線程安全的類設計。我只是想了解我使用的模式是否是最好的解決方案之一。當然,在任何特定情況下的最佳解決方案都依賴於問題。以下幾個答案包含應考慮的替代設計。
編輯:此外,有多個線程安全的定義。例如,在上面我的實現,下面的代碼不會是線程安全的:
var myObject = new ThreadSafeClass();
myObject.PropertyA++; // NOT thread-safe
因此,沒有上面的類定義代表了一個好辦法?如果不是,那麼對於具有類似行爲的設計,您會推薦哪種設計,這些設計對於類似的用途是線程安全的?
請先搜索:http://stackoverflow.com/search?q=What+is+the+Best+Practice+for+Creating+Thread-Safe+Classes+in+C%23 – 2010-01-25 20:06:33
嗯。在你的代碼中,你使用相同的鎖對象來讀取PropertyA和PropertyB。這意味着一個讀取PropertyA的線程會鎖定另一個嘗試讀取PropertyB的內容,直到第一個線程完成。那是你要的嗎?如果這是我的課程,我會爲每個吸氣器創建一個單獨的讀取鎖定器,然後設置者也必須尊重該鎖定。請參閱下面的答案。 – 2010-01-25 20:44:48
我只是低估了你,因爲沒有單一的方法來產生一個線程安全的類。對這個問題的任何回答都有可能給未來的讀者帶來錯誤的印象。 – 2010-01-26 01:06:09