5

One of my classes has a property of type Guid. This property can read and written simultaneously by more than one thread. I'm under the impression that reads and writes to a Guid are NOT atomic, therefore I should lock them.

I've chosen to do it like this:

public Guid TestKey
{
    get
    {
        lock (_testKeyLock)
        {
            return _testKey;
        }
    }

    set
    {
        lock (_testKeyLock)
        {
            _testKey = value;
        }
    }
}

(Inside my class, all access to the Guid is also done through that property rather than accessing _testKey directly.)

I have two questions:

(1) Is it really necessary to lock the Guid like that to prevent torn reads? (I'm pretty sure it is.)

(2) Is that a reasonable way to do the locking? Or do I need to do it like the following:

get
{
    Guid result;

    lock (_testKeyLock)
    {
        result = _testKey;
    }

    return result;
}

[EDIT] This article does confirm that Guids will suffer from torn reads: http://msdn.microsoft.com/en-us/magazine/jj863136.aspx

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276

2 Answers2

8

1: yes; to protect from torn values if you have one thread reading and one writing; Guid is not guaranteed to be atomic

2: "like the following": they are effectively the same; at the IL level you cannot ret from a try/catch block, so the compiler implements your first example by introducing a local variable, just like in your second example.

Another approach might be to box it; a reference is atomic:

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

No locking required, but a small overhead from the box.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
4

1) Is it really necessary to lock the Guid like that to prevent torn reads? (I'm pretty sure it is.)

Yes it is.

2) Is that a reasonable way to do the locking?

Again: Yes.

If there had existed an Interlocked method for Guid then that would have been better (faster).

For double (another non-atomic struct) there is support from Interlocked and for references it is not needed.

So as a pattern this is only required for larger structs that are not supported by Interlocked.

H H
  • 263,252
  • 30
  • 330
  • 514
  • There's not that much to elaborate on - copying Guids is not atomic. All the info is already part of the question. – H H Feb 01 '13 at 13:58