使 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

使 Guid 属性线程安全

1:是的; 如果您有一个线程读取和一个写入,则防止值撕裂; Guid不能保证是原子的

2:"像下面这样":它们实际上是相同的;在 IL 级别,您无法try/catchret,因此编译器通过引入局部变量来实现您的第一个示例,就像您的第二个示例一样。

另一种方法可能是将其装箱;引用原子的:

object boxedTestKey;
public Guid TestKey
{
    get { return (Guid)boxedTestKey; }
    set { boxedTestKey = value; }
}

无需锁定,但距离盒子只有很小的开销。

1)真的有必要像这样锁定Guid以防止撕裂读取吗?(我很确定是这样。

是的,它是。

2)这是进行锁定的合理方法吗?

再次:是的。

如果存在一种Interlocked Guid方法,那么那会更好(更快)。

对于double(另一个非原子结构),有来自Interlocked的支持,对于引用,则不需要。

因此,作为一种模式,这仅适用于 Interlocked 不支持的较大结构。