Reproduced from the blog Garden Small Juan:
https://kb.cnblogs.com/page/88513/
The definition of MSDN is given first:
The lock keyword can be used to ensure that a block of code finishes running without being interrupted by another thread. This is achieved by obtaining a mutex for a given object during the code block run.
Let's take a look at the execution process, with the following code examples:
Assuming that thread a executes first, thread B is slightly slower. Thread A executes to the lock statement and determines if obj has applied for the mutex, judging by the existence of an object on a per-existing lock. ReferenceEquals comparison (not shown here), if it does not exist, then request a new mutex, then thread a enters lock.
This assumes that thread B is started, and thread A has not finished executing the code inside lock. Thread B executes to the lock statement, checks that obj has applied for the mutex, waits until thread a finishes executing, releases the mutex, and thread B can request a new mutex and execute the code inside the lock.
Next, say something about what the lock object is.
Why not lock value types, such as lock (1)? Lock essentially monitor.enter,monitor.enter the value type, each time the lock is a boxed object. Lock is actually a compiler-like syntax sugar, so the compiler directly restricts the lock value type. Step back 10,000 to say, even if the compiler allows you to lock (1), but object. ReferenceEquals always returns False (since each boxing is a different object), that is, each time it is judged not to request a mutex, so that at the same time, other threads can still access the inside of the code, does not achieve the effect of synchronization. Likewise, lock (object) 1 is not.
What about the lock ("xxx") string? The exact words on MSDN are:
Locking a string is especially risky because the string is persisted by the common language runtime (CLR). This means that there is only one instance of any given string in the entire program, which is the same object that represents the text in all the threads of all running application domains. Therefore, whenever a lock is placed on a string that has the same content anywhere in the application process, all instances of that string in the application are locked. In general, it is a good idea to avoid locking public types or locking object instances that are not under application control. For example, if the instance can be publicly accessible, lock (this) may be problematic because uncontrolled code may also lock the object. This can result in a deadlock, where two or more threads wait to release the same object. For the same reason, locking public data types (compared to objects) can also cause problems. and lock (this) is only valid for the current object, if the synchronization effect is not achieved between multiple objects.
Lock (typeof (Class)) is too wide to be the same as a locked string. Some system classes provide members that are dedicated to locking. For example, the Array type provides SyncRoot. Many collection types also provide SyncRoot. The custom class recommends using private read-only static objects, such as: private static readonly Object obj = new Object (); Why should I set it to read-only? This is because if you change the value of obj in the lock code snippet, the other threads are unblocked because the mutex object has changed. ReferenceEquals must return FALSE.
Unity lock keyword