我有一个有两个属性和两个方法的类。比如下面的那个。(请忽略数据类型或返回类型,这只是一个典型的场景)
// The methods could be invoked by multiple threads
public class Stock
{
private static int FaceValue {get; set;}
private static int Percent (get; set;}
// method that updates the two properties
Public void UpdateStock()
{
FaceValue += 1;
Percent = FaceValue * 100;
}
// method that reads the two properties
public int[] GetStockQuote()
{
return new int[] { FaceValue, Percent};
}
}我需要确保这个类是线程安全的。我可以在这两种方法中使用lock(obj)作为一种使其成为线程安全的技术,但考虑到以下几点,使其线程安全的最佳技术是什么:
只是想知道我是在思考这一权利,还是可能是,我考虑这些问题过于复杂了。事先非常感谢你帮我弄清楚这件事。
Mani
发布于 2012-10-08 15:51:52
一般来说,lock可能是这里最简单的方法。
一个可能更好的选择是使这个类不可变。如果在创建类后不能更改类中的值,则在读取值时不必再担心,因为它们是无法修改的。
在本例中,这可以通过使用两个值的构造函数来完成,并将UpdateStock更改为更类似于:
public Stock GetUpdatedStock()
{
// Create a new instance here...
return new Stock(this.FaceValue + DateTime.Now.MilliSecond, this.FaceValue * 100);
}编辑:
现在您已经实现了FaceValue和百分比静态,您将需要同步。在这里,lock可能是最简单的选择。
使用单个值,您可以使用联锁类原子地处理更新,但是没有办法对两个值进行原子更新*,这很可能是正确执行线程安全所必需的。在这种情况下,通过lock同步将解决您的问题。
*注意:如果将两个值都放在一个类中,并交换整个类实例,这可能不需要通过Interlocked.CompareExchange进行锁定,但这可能会带来比它更大的麻烦。
发布于 2012-10-08 16:17:14
没有使线程安全的银弹解决方案,每个场景都需要自己的解决方案。最明显的是使用lock,但在您的示例中,您可以简化和使用Interlocked类,并让它成为一个原子操作:
public class Stock
{
private static int FaceValue {get; set;}
Public void UpdateStock()
{
//only a single property to update now
Interlocked.Increment(FaceValue);
}
// method that reads the two properties
public int[] GetStockQuote()
{
var currVal = FaceValue;
return new int[] { currVal, currVal * 100 };
}
}请参阅MSDN上的互锁。
https://stackoverflow.com/questions/12785043
复制相似问题