Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making Guid properties threadsafe

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

like image 209
Matthew Watson Avatar asked Feb 01 '13 13:02

Matthew Watson


2 Answers

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.

like image 177
Marc Gravell Avatar answered Nov 05 '22 02:11

Marc Gravell


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.

like image 4
Henk Holterman Avatar answered Nov 05 '22 01:11

Henk Holterman