使自定义对象线程安全

我发布了一个关于返回集合的早期问题 ,并且出现了线程安全的主题。 我得到了这个链接来做更多的阅读,我找到了这个特定的行:

通常,避免锁定公共类型或超出代码控制范围的实例。

首先,如果我错了,请纠正我,但微软是否锁定公共类型,即平衡变量?

其次,我将如何锁定自己的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属性线程安全?

当您需要锁定变量时,需要锁定使用变量的每个位置。 锁不是变量 – 它是用于使用变量的代码区域。

如果你只是在一个地方阅读也没关系 – 如果你需要锁定一个变量,你需要在任何地方使用该变量。

lock的替代方法是Interlocked类 – 它使用处理器级原语来锁定更快一点。 但是, Interlocked无法保护多个语句(并且具有2个Interlocked stataments与在单个lock中包含这2个语句不同)。

锁定时, 必须锁定引用类型的实例(在大多数情况下(但不总是),它也应该是静态实例)。 这是为了确保所有锁实际上都在同一个实例上取出,而不是它的副本。 显然,如果您在不同的地方使用副本,则不会锁定相同的内容,因此您的代码将无法正确序列化。

例如:

 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进行简单的get / set不需要锁定 – 读取和写入32位值(自身内部)本身就是primefaces的。 所以这个例子太简单了 – 只要你不尝试在应该以primefaces方式完成的多个操作中使用ID ,就不需要锁定。 但是,如果您的实际代码实际上更复杂, ID被检查和设置,您可能需要锁定,并且您需要锁定构成primefaces操作的所有操作 。 这意味着您可能必须从getter / setter中取出锁定 – 变量的get / set对上的2个锁定与它们周围的单个锁定不同。

你应该像这样在Person类中定义一个变量

 private readonly object _lock_ = new Object(); 

如果要在Person所有实例上进行同步,则应将其设置为static

然后,当你想要锁定时,你可以这样做

 lock(_lock_) //whose there? it's me, I kill you! oops sorry that was knock knock { //do what you want } 

我建议你阅读这些文章。 1,2

关于Microsoft文章的第一个问题的答案:不。该文章没有锁定balance变量。 它锁定私有的thisLock变量。 所以这个例子很好。

其次,根据您发布的代码,您不需要添加任何锁定来使您的类线程安全,因为您的数据是不可变的。 一旦创建了Person的实例并从构造函数中设置了Identification属性的值,您的类设计就不允许该属性再次更改。 这是不变的,而这本身就提供了线程安全性。 所以你不需要费心添加锁等。 再次,假设您的代码示例是准确的。

编辑:此链接可能对您有用。