Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# thread safe static member

I have a C# class with a static member, that is read from multiple threads and written in one thread.

As far as I know Uint64 read and write is not an atomic operation on all systems, so I have to manually guarantee thread safety.

I had a few ideas about how to do this.

  1. Do it with and atomic wrapper class, like std::atomic in c++. Is there something similar implemented in C#?

  2. Use the volatile modifier with static field. However this is not allowed. Why?

  3. I finally did the following:

    private static object tick_time_lock;
    private static UInt64 _currentTickTime;
    public static UInt64 CurrentTickTime 
    {
        get
        {
            return _currentTickTime;
        }
        set
        {
            lock (tick_time_lock)
            {
                _currentTickTime = value;
            }
        }
    }
    

Is this the correct way of making this field thread-safe?

like image 482
VSZM Avatar asked Nov 25 '13 23:11

VSZM


2 Answers

Is this the correct way of making this field thread-safe?

A monitor lock is meaningless unless all accesses of a given resource are synchronized. Putting a lock around the set accessor is rather useless unless you also lock on the get accessor. As you say, reads and writes of UInt64 values are not atomic on all platforms. What happens if the field is read in the get accessor when only the first word has been written in the set accessor? You'd get a torn read.

Use the volatile modifier with static field. However this is not allowed. Why?

The C# language designers felt it was beneficial to guarantee that all volatile field accesses are atomic. As a trade-off, you cannot declare any 64-bit field as volatile. I do not know for certain why this decision was made. Perhaps they wanted to avoid adding "hidden" overhead to some volatile read/write operations and instead require developers to depend on framework-level facilities like Thread.Volatile[Read/Write](ref long) for handling 64-bit values.

Do it with and atomic wrapper class, like std::atomic in c++. Is there something similar implemented in C#?

Yes. There are framework-level atomic operations exposed through the System.Threading.Interlocked class, including Read, Exchange, CompareExchange.

like image 175
Mike Strobel Avatar answered Oct 06 '22 00:10

Mike Strobel


Look at Interlocked class, it provides atomic operations for variables that are shared by multiple threads.

like image 40
Kirill Polishchuk Avatar answered Oct 05 '22 23:10

Kirill Polishchuk