使Guid属性线程安全

时间:2013-02-01 13:52:13

标签: c# multithreading

我的一个类有一个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

2 个答案:

答案 0 :(得分:8)

1:是的;如果你有一个线程读数和一个写入,以防止撕裂的价值; Guid不保证是原子的

2:“喜欢以下”:它们实际上是一样的;在IL级别,您<{>}} / ret不能 try,因此编译器通过引入局部变量来实现您的第一个示例,就像在您的第二个例子。

另一种方法可能是把它包装起来;引用原子:

catch

不需要锁定,但只需要一小段开销。

答案 1 :(得分:4)

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

是的。

2)这是一种合理的锁定方式吗?

再次:是的。

如果Interlocked存在Guid方法,则会更好(更快)。

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

因此,只有Interlocked不支持的较大结构才需要这种模式。