I am trying to implement a synchronization algorithm in C # without success.
Why is the following code safe?
using System; using System.Threading; namespace SoftwareLockTest { class Program { private static volatile bool _isLocked1 = false; private static volatile bool _isLocked2 = false; private static volatile int _count = 0; static void Main(string[] args) { Thread thread2 = new Thread(Thread2Work); thread2.Start(); Thread1Work(); } public static void Thread1Work() { while (true) { _isLocked1 = true; while (_isLocked2) { _isLocked1 = false; while (_isLocked2) ; _isLocked1 = true; } CriticalSection(); _isLocked1 = false; } } public static void Thread2Work() { while (true) { _isLocked2 = true; while (_isLocked1) { _isLocked2 = false; while (_isLocked1) ; _isLocked2 = true; } CriticalSection(); _isLocked2 = false; } } private static void CriticalSection() { if (_count != 0) { Console.WriteLine("NOT THREAD SAFE 1"); _count = 0; } _count++; if (_count != 1) { Console.WriteLine("NOT THREAD SAFE 2"); } _count--; if (_count != 0) { Console.WriteLine("NOT THREAD SAFE 3"); } } } }
The problem is that the record followed by the read can be reordered (even with "volatile"). You need to call Thread.MemoryBarrier (); before four while loops (_isLockedX).
Please read http://www.albahari.com/threading/part4.aspx for an explanation of memory barriers and instability.
, , , .
. , , . , , - . , .
, . "" , , . , . , , concurrency, 5 , .
, , , , lock/Monitor, Interlocked (.Increment)/ (.Decrement)/test (.CompareExchange). , volatile , ++/-- .
lock
Monitor
Interlocked
.Increment
.Decrement
.CompareExchange
volatile
++
--
, , lock, . - ", ", " ".
, , , ... , , volatile, , , , .
, , : " , , , ". ( , MSDN , , ).
, , , . , , , , "" ... ( , )
, codeguru ... , , , .
, . x86 SC. .
, -:
thread1: WRITE _isLocked1, 1 READ _isLocked2 (skip the while loop) critical section WRITE _isLocked1, 0 thread2: WRITE _isLocked2, 1 READ _isLocked1 (skip the while loop) critical section WRITE _isLocked2, 0
, thread1 , 2, , ( 1, 0). 2 1 . , , - , , 1 thread2, , ( ).
AMD, 2, 7.2, , x86.
lock?
lock (_anyInstantiatedObject) { CriticalSection(); }
Thus, you rely on the OS to ensure that no other thread enters the critical section at the same time.
Source: https://habr.com/ru/post/1727051/More articles:moving package / CMD does not work with folders - windows-7PHP repeats duplicate lines only once - phpMono XSP игнорирует директиву в Web.Config - asp.netcommand line function for querying and returning input - scriptingincluding php in tag - phpHow to insert $ variable in jQuery - jquerycheck any content in php - postIs there a view for the button bar? (Link to the image describing the performance) - androidWhich Android control to use? - androidWhat third-party user interface libraries for WinForms, WPF, MVC, etc. Are the best? - asp.netAll Articles