I've been reading this book from Joseph Albahari about threading:
http://www.albahari.com/threading/
In Part 2, I found this example:
http://www.albahari.com/threading/part2.aspx#_When_to_Lock
Here is the aforementioned example:
class ThreadUnsafe
{
static int _x;
static void Increment() { _x++; }
static void Assign() { _x = 123; }
}
Thread-safe version:
class ThreadSafe
{
static readonly object _locker = new object();
static int _x;
static void Increment() { lock (_locker) _x++; }
static void Assign() { lock (_locker) _x = 123; }
}
I couldn't understand why Assign method is not thread safe. Shouldn't integer assignment be atomic operation on both 32- and 64-bit architectures?
Conditionally safe: Different threads can access different objects simultaneously, and access to shared data is protected from race conditions. Not thread safe: Data structures should not be accessed simultaneously by different threads.
Being thread-safe would mean that any operation modifying the list would need to be interlocked against simultaneous access. This would be necessary even for those lists that will only ever be used by a single thread. That would be very inefficient. Save this answer.
To test if the combination of two methods, a and b, is thread-safe, call them from two different threads. Put the complete test in a while loop iterating over all thread interleavings with the help from the class AllInterleavings from vmlens. Test if the result is either an after b or b after a.
The assignment is atomic in that any reading thread will either see 123 or the previous value - not some intermediate value. However, there's no guarantee that a thread will see the new value until there have been two memory barriers: a write memory barrier in the writing thread, and a read memory barrier in the reading thread.
If you had two threads like this (after making _x
public or internal, so that it could be read from other types of course - or with the code in the ThreadSafe
class anyway):
// Thread 1
Console.WriteLine("Writing thread starting");
ThreadSafe.Assign();
Console.WriteLine("Writing thread done");
// Thread 2
Console.WriteLine("Reading thread starting");
while (ThreadSafe._x != 123)
{
// Do nothing
}
Console.WriteLine("Reading thread done");
... there's no guarantee that thread 2 would ever finish, because thread 2 might not "see" the assignment from thread 1.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With