我发布了关于返回集合的earlier question,并且出现了线程安全主题。我得到了这个link来做更多的阅读,我找到了这个特殊的界限:
一般情况下,避免锁定公共类型或超出您的实例 代码的控制。
首先,如果我错了,请纠正我,但微软是否锁定公共类型,即余额变量?
其次,我将如何锁定自己的getter / setter属性。假设我有以下课程:
private int ID;
public Person(int id)
{
this.Identification= id;
}
public int Identification
{
get { return this.ID; }
private set
{
if (value == 0)
{
throw new ArgumentNullException("Must Include ID#");
}
this.ID = value;
}
}
吸气剂公开正确吗?只有setter被声明为private。那么,我如何锁定,或使我的getter / setter属性线程安全?
答案 0 :(得分:4)
您应该在CKEDITOR.instances['cm_ckeditor'].getData()
类中定义一个变量,如此
Person
如果您要对private readonly object _lock_ = new Object();
的所有实例进行同步,则应将其设为Person
。
然后当你想要锁定时,你可以这样做
static
答案 1 :(得分:1)
当您需要锁定变量时,您需要锁定使用该变量的每个位置。锁不是变量 - 它是用于使用变量的代码区域。
如果您只是在一个地方阅读,那么无关紧要 - 如果您需要锁定变量,则需要无处不在使用该变量。
lock
的替代是Interlocked
类 - 它使用处理器级原语进行锁定,速度更快一些。 Interlocked
但是无法保护多个语句(并且有两个Interlocked
个数字与在单个lock
中包含这两个语句不同。)
锁定时,必须锁定引用类型的实例(在大多数情况下(但不总是),它也应该是静态实例)。这是为了确保所有锁实际上都在相同的实例上取出,而不是它的副本。显然,如果您在不同的地方使用副本,则不会锁定相同的内容,因此您的代码将无法正确序列化。
例如:
private static readonly object m_oLock = new object ();
...
lock ( m_oLock )
{
...
}
使用非静态锁是否安全需要对代码进行详细分析 - 在某些情况下,它会导致更多的并行性,因为相同的代码区域被锁定较少但是对它的分析可能非常棘手 - 如果你不确定,只需使用static
锁定对象。采用开放锁定的成本很小,但不正确的分析可能会导致需要花费很长时间才能进行调试的错误。
修改强>
这是一个显示如何锁定属性访问的示例:
private int ID; // do NOT lock on value type instances
private static readonly object Lock = new object ();
public Person(int id)
{
this.Identification = id;
}
public int Identification
{
get
{
lock ( Lock )
{
return this.ID;
}
}
private set
{
if (value == 0)
throw new ArgumentNullException("Must Include ID#");
lock ( Lock )
{
this.ID = value;
}
}
}
由于您的属性只执行简单的get / set操作,因此您可以尝试使用Interlocked.CompareExchange
而不是完全锁定 - 它会使事情稍微快一些。但请记住,互锁操作与锁定不同。
编辑2:
还有一件事:int
上的一个简单的获取/设置不需要锁定 - 读取和写入32位值(本身)本身就是原子的。所以这个例子太简单了 - 只要你不尝试在应该以原子方式完成的多个操作中使用ID
,就不需要锁定。但是,如果您的实际代码在检查和设置ID
时实际上更复杂,则可能需要锁定并且您需要锁定组成原子操作的所有操作。这意味着您可能必须从getter / setter中取出锁定 - 变量的get / set对上的2个锁定与它们周围的单个锁定不同。
答案 2 :(得分:1)
关于Microsoft文章的第一个问题的答案:
不。该文章没有锁定balance
变量。它锁定私有thisLock
变量。所以这个例子很好。
其次,根据您发布的代码,您不需要添加任何锁定来使您的类线程安全,因为您的数据是不可变的。创建Person
的实例并在构造函数中设置Identification
属性的值后,您的类设计不允许该属性再次更改。这是不变的,而这本身就提供了线程安全性。所以你不需要费心添加锁等。再次,假设您的代码示例是准确的。
编辑: 这个link可能对您有用。