Why do bool volatile with multithreading in C #?

I understand the volatile keyword in C ++ well. But in C #, this apparently has a different meaning, more related to multithreading. I thought the bool operations are atomic, and I thought that if the operation is atomic, you will not have problems with threads. What am I missing?

https://msdn.microsoft.com/en-us/library/x13ttww7.aspx

+6
source share
2 answers

The volatile keyword in C # refers to read / write reordering, so this is something rather esoteric.

http://www.albahari.com/threading/part4.aspx#_Memory_Barriers_and_Volatility

(which I consider one of the "bibles" about streaming processing) writes:

The volatile keyword instructs the compiler to generate a binding for each reading from this field and a lock for each record in this field. The fence-fence prevents the movement of other readings / records before the fence; The shutter fence prevents the movement of other reads / records after the fence. These midfielders are faster than full fences because they give lead time and equipment more room for optimization.

This is something completely unreadable :-)

Now ... What does this not mean:

  • This does not mean that the value will be read now / will be written now

it just means that if you read something from a mutable variable, everything else that was read / written before this β€œspecial” read will not be moved after that β€œspecial” read. Therefore, it creates a barrier. It is ironic that by reading from a mutable variable, you guarantee that all the records that you made with any other variable (volatile or not) at the reading point will be executed.

Volatile recording is something more important, and it is partially guaranteed by the Intel processor, and what was not guaranteed by the first version of Java: there is no reordering of the recording. The problem was this:

 object myrefthatissharedwithotherthreads = new MyClass(5); 

Where

 class MyClass { public int Value; MyClass(int value) { Value = value; } } 

Now ... this expression can be represented as:

 var temp = new MyClass(); temp.Value = 5; myrefthatissharedwithotherthreads = temp; 

where temp is something generated by the compiler that you don't see.

If the entries can be reordered, you can:

 var temp = new MyClass(); myrefthatissharedwithotherthreads = temp; temp.Value = 5; 

and another thread could see the partially initialized MyClass , because the value of myrefthatissharedwithotherthreads can be read before the initialization of the MyClass class is complete.

+3
source

I thought bool operations were atomic

They are truly atomic.

and I thought that if the operation was atomic, you would have no problems with threads.

This is where you have an incomplete picture. Imagine that on different cores there are two threads, each of which has its own cache levels. Thread # 1 has foo in its cache, and Thread # 2 updates the value of foo . Topic # 1 will not see the change if foo not marked as volatile , acquired a lock , used the Interlocked class, or explicitly called Thread.MemoryBarrier() , which will cause the value to be invalid in the cache. This ensures that you read the most recent value :

Using a mutable modifier ensures that one thread retrieves the most up-to-date value written by another thread.

Eric Lippert has a great post on volatility, where he explains:

The true semantics of erratic reads and writes are much more complex than I described here; in fact, they do not guarantee that each processor stops what it is doing and updates the caches to / from main memory. . Rather, they provide weaker guarantees on how to access memory before and after reading, and you may notice that the order is ordered relative to each other.

Edit:

According to @xanatos comment, this does not mean that volatile guarantees immediate reading, it guarantees reading the most updated value.

+4
source

Source: https://habr.com/ru/post/987323/


All Articles