Ant*_*ean 15 .net c# singleton multithreading thread-safety
我有一个多个类使用的C#单例类.是通过线程安全Instance的Toggle()方法访问?如果是,通过什么假设,规则等.如果不是,为什么以及如何解决它?
public class MyClass
{
private static readonly MyClass instance = new MyClass();
public static MyClass Instance
{
get { return instance; }
}
private int value = 0;
public int Toggle()
{
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
return value;
}
}
Run Code Online (Sandbox Code Playgroud)
Ori*_*rds 28
是通过'Instance'访问'Toggle()'类threadafe吗?如果是,通过什么假设,规则等.如果不是,为什么以及如何解决它?
不,这不是线程安全的.
基本上,两个线程可以同时运行该Toggle函数,因此可能会发生这种情况
// thread 1 is running this code
if(value == 0)
{
value = 1;
// RIGHT NOW, thread 2 steps in.
// It sees value as 1, so runs the other branch, and changes it to 0
// This causes your method to return 0 even though you actually want 1
}
else if(value == 1)
{
value = 0;
}
return value;
Run Code Online (Sandbox Code Playgroud)
您需要按照以下假设进行操作.
如果2个线程正在运行,它们可以并且将在任何点随机交错并相互交互.您可以在写入或读取64位整数或浮点数(在32位CPU上)的一半,另一个线程可以跳入并从您下面更改它.
如果2个线程永远不会访问任何共同点,那么无关紧要,但只要它们这样做,就需要防止它们踩到彼此的脚趾.在.NET中执行此操作的方法是使用锁.
您可以通过考虑以下事情来决定锁定的内容和位置:
对于给定的代码块,如果something从我的下面改变了get 的值,那会有关系吗?如果愿意,您需要something在代码的持续时间内将其锁定.
再看一遍你的例子
// we read value here
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
// and we return it here
return value;
Run Code Online (Sandbox Code Playgroud)
为了使它返回我们期望的内容,我们假设value在read和the之间不会改变return.为了使此假设实际上正确,您需要锁定value该代码块的持续时间.
所以你这样做:
lock( value )
{
if(value == 0)
... // all your code here
return value;
}
Run Code Online (Sandbox Code Playgroud)
然而
在.NET中,您只能锁定引用类型.Int32是一种值类型,因此我们无法锁定它.
我们通过引入"虚拟"对象,并锁定解决这个那个地方,我们会想锁定"价值".
这就是Ben Scheirman所指的.
Ben指出,原始的补充不是线程安全的
使线程安全的一种简单方法是引入一个lock语句.例如.像这样:
public class MyClass
{
private Object thisLock = new Object();
private static readonly MyClass instance = new MyClass();
public static MyClass Instance
{
get { return instance; }
}
private Int32 value = 0;
public Int32 Toggle()
{
lock(thisLock)
{
if(value == 0)
{
value = 1;
}
else if(value == 1)
{
value = 0;
}
return value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6071 次 |
| 最近记录: |