0

According to the Joe Albahari's book Threading in C# reading and writing a field having a size less than or equal to 32 bits is an atomic operation: this implies that in such a scenario it's not possible ending up with a torn read (here you can find a simple way to reproduce a torn read by using a decimal field).

Given that, consider the following C# console application:

using System;
using System.Threading;

namespace ConsoleApp2
{
  class Program
  {
    static void Main(string[] args)
    {
      var obj = new Test();
      var random = new Random();

      var thread1 = new Thread(() =>
      {
        while (true)
        {
          Console.WriteLine($"The boolean value is {obj.field}");
        }
      });

      var thread2 = new Thread(() =>
      {
        while (true)
        {
          obj.field = (random.Next() % 2) == 0;
        }
      });

      thread1.Start();
      thread2.Start();
    }
  }

  class Test
  {
    public bool field;
  }
}

My question is: when I run such a program, what exactly happens in the memory address containing the value of the field being written and read concurrently by the two threads ? Is it possible to corrupt its value doing so ?

Based on my understanding, there is a concurrent access to the same memory address at the same time:

  1. can I get any kind of runtime exception doing so ?
  2. is the underlying processor able to handle such a scenario without errors ?

Putting the question in a more general way: when two threads concurrently read and write a 32 bits value the only possible issue is that there is no guarantee about the value being read (I mean that the value read is completely indeterminate due to the concurrent write operation) ?

Enrico Massone
  • 6,464
  • 1
  • 28
  • 56
  • Even if you have true concurrency (multiple cores), there's the whole topic of "Cache Coherence" to ensure that cores don't see torn writes. But it's quite complex to try to cover in a Q+A format. – Damien_The_Unbeliever Oct 22 '18 at 14:29

1 Answers1

3

1.can I get any kind of runtime exception doing so ?

Nope. Modern processors have a way of blocking other cores for exclusive (write) access to the same address similar to a spin lock. (the actual implementation varies between processors)

2.is the underlying processor able to handle such a scenario without errors ?

Yes, all aligned 4 bytes writes (or 8 bytes for 64bit os) are guarantee to be atomic in a sense that you can't get corrupted data (2 bytes from core1 and 2 bytes from core2). However if the write is > 8 bytes or goes off aligned boundary (ex. big integer) then you could get into corrupted memory situation if it was done without lock.

Ofc there is always the chance of processor implementation screws up and in that case you are SOL

Steve
  • 11,696
  • 7
  • 43
  • 81
  • @dymanoid I don't think you can do unaligned access in c#, so that's out of the question – Steve Oct 22 '18 at 15:11
  • Actually, [you can](https://stackoverflow.com/questions/15249626/are-reads-and-writes-to-unaligned-fields-in-net-definitely-atomic) and the access is not guaranteed to be atomic. – dymanoid Oct 22 '18 at 15:13
  • @EnricoMassone, this answer is not correct, because it doesn't cover the unaligned access. Please refer to [this question](https://stackoverflow.com/questions/15249626/are-reads-and-writes-to-unaligned-fields-in-net-definitely-atomic) and also read [this good answer](https://stackoverflow.com/a/36685056/2846483) (despite it's tagged C++, the information provided is very useful). – dymanoid Oct 22 '18 at 15:19
  • @dymanoid fixed. Never know you can shoot yourself in the foot like that lol – Steve Oct 22 '18 at 15:53