5

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

4

2 回答 2

8

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

2:“如下所示”:它们实际上是相同的;在 IL 级别,您不能 rettry/catch块,因此编译器通过引入局部变量来实现您的第一个示例,就像在您的第二个示例中一样。

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

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

不需要锁定,但盒子的开销很小。

于 2013-02-01T13:55:56.623 回答
4

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

是的。

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

再次:是的。

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

对于double(另一个非原子结构),Interlocked不需要引用,也不需要引用。

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

于 2013-02-01T13:55:22.690 回答