使 Guid 属性线程安全
本文关键字:安全 线程 属性 Guid | 更新日期: 2023-09-27 17:56:55
我的一个类具有 Guid 类型的属性。此属性可以由多个线程同时读取和写入。我的印象是读取和写入 Guid 不是原子的,因此我应该锁定它们。
我选择这样做:
public Guid TestKey
{
get
{
lock (_testKeyLock)
{
return _testKey;
}
}
set
{
lock (_testKeyLock)
{
_testKey = value;
}
}
}
(在我的类中,对 Guid 的所有访问也是通过该属性完成的,而不是直接访问_testKey。
我有两个问题:
(1)真的有必要像这样锁定Guid以防止撕裂读取吗?(我很确定是这样。
(2)这是合理的锁定方式吗?或者我需要像下面这样做:
get
{
Guid result;
lock (_testKeyLock)
{
result = _testKey;
}
return result;
}
[编辑] 这篇文章确实证实了Guids将遭受撕裂的阅读:http://msdn.microsoft.com/en-us/magazine/jj863136.aspx
1:是的; 如果您有一个线程读取和一个写入,则防止值撕裂; Guid
不能保证是原子的
2:"像下面这样":它们实际上是相同的;在 IL 级别,您无法从 try
/catch
块ret
,因此编译器通过引入局部变量来实现您的第一个示例,就像您的第二个示例一样。
另一种方法可能是将其装箱;引用是原子的:
object boxedTestKey;
public Guid TestKey
{
get { return (Guid)boxedTestKey; }
set { boxedTestKey = value; }
}
无需锁定,但距离盒子只有很小的开销。
1)真的有必要像这样锁定Guid以防止撕裂读取吗?(我很确定是这样。
是的,它是。
2)这是进行锁定的合理方法吗?
再次:是的。
如果存在一种Interlocked
Guid
方法,那么那会更好(更快)。
对于double
(另一个非原子结构),有来自Interlocked
的支持,对于引用,则不需要。
因此,作为一种模式,这仅适用于 Interlocked
不支持的较大结构。