使自定义对象线程安全
我发布了一个关于返回集合的早期问题 ,并且出现了线程安全的主题。 我得到了这个链接来做更多的阅读,我找到了这个特定的行:
通常,避免锁定公共类型或超出代码控制范围的实例。
首先,如果我错了,请纠正我,但微软是否锁定公共类型,即平衡变量?
其次,我将如何锁定自己的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
属性的值,您的类设计就不允许该属性再次更改。 这是不变的,而这本身就提供了线程安全性。 所以你不需要费心添加锁等。 再次,假设您的代码示例是准确的。
编辑:此链接可能对您有用。