HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Generic thread-safe data structure

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
genericthreadstructuresafedata

Problem

I wrote the following class so that a single object can be shared across many threads. Is using the ReaderWriterLockSlim redundant in this case and only Interlocked.Funcs() can do the job and ensure thread safety?

using System.Threading;

public class SharedData where T:class
{
T _data;
ReaderWriterLockSlim _lock;

public SharedData(T arg)
{
    Interlocked.Exchange(ref _data, arg);
    _lock = new ReaderWriterLockSlim();
}

public T Value
{
    get
    {
        _lock.EnterReadLock();
        var ret = Interlocked.CompareExchange(ref _data, default(T), default(T));
        _lock.ExitReadLock();

        return ret;
    }
    set
    {
        _lock.EnterWriteLock();
        Interlocked.Exchange(ref _data, value);
        _lock.ExitWriteLock();
    }
}
}

Solution

Using Interlocked on a class reference grants atomic transaction when you exchange an object for another;

For example, using

Interlocked.Exchange(ref _data, value);


will exchange an object for an other, returning the previous object.

ReaderWriterLockSlim will protect some parts of your code, and you could also protect the object get/set with it.

Use only one of the lock, not both !

Also, you don't need usually to protect the initial set statement in your Ctor. Basically, you can only create a new object once in only one thread, before sharing anything related to this object.

One last point, with this code you are protecting the object reference, not the object itself. See below ...

class MyString {
    public string Data {get; set;}
}
...
var myString = new MyString() ;
var mySharedString = new SharedData(myString) ;
...    
... thread 1
... mySharedString.Value.Data = "Hello" ;
...
... thread 2
... mySharedString.Value.Data = "BAD" ;


If the shared object is ReadOnly, it works, if the object is mutable, it will fail badly.

Code Snippets

Interlocked.Exchange<T>(ref _data, value);
class MyString {
    public string Data {get; set;}
}
...
var myString = new MyString() ;
var mySharedString = new SharedData<MyString>(myString) ;
...    
... thread 1
... mySharedString.Value.Data = "Hello" ;
...
... thread 2
... mySharedString.Value.Data = "BAD" ;

Context

StackExchange Code Review Q#145625, answer score: 3

Revisions (0)

No revisions yet.