I. Why do you have to Lock,lock?
When we use threads, the most efficient way is, of course, asynchronous, where each thread runs at the same time and does not depend on and waits on each other. However, when different threads need to access a resource, it is necessary to synchronize the mechanism, that is, when reading and writing the same resource, we have to make the resource can only be manipulated by one thread at a time to ensure that each operation is effective and instantaneous, that is, the atomicity of its operation. Lock is the most commonly used synchronization method in C #, in the form of lock (OBJECTA) {codeb}.
Lock (OBJECTA) {Codeb} looks simple and actually has three meanings, which is essential for proper use:
1. Has objecta been lock? No, I'll lock it, or I'll wait until Objecta is released.
2. After lock is executed codeb other threads cannot call Codeb and cannot use Objecta.
3. Objecta is released after execution of Codeb, and codeb can be accessed by other threads.
Two. What happened to lock (this)?
Let's look at an example:
classC1 {Private BOOLdeadlocked =true;//This method uses lock, and we want lock's code to be accessible only by one thread at a time Public voidLockme (Objecto) { Lock(locker) { while(deadlocked) {deadlocked= (BOOL) O; Console.WriteLine ("foo:i am Locked:("); Thread.Sleep ( -); } } } //methods that all threads can access concurrently Public voidDonotlockme () {Console.WriteLine ("I am not locked:)"); } }
classProgram {Static voidMain (string[] args) {C1 C1=NewC1 (); //call Lockme in the T1 thread and set deadlock to True (deadlock will occur)Thread T1 =NewThread (C1. Lockme); T1. Start (true); Thread.Sleep ( -); //in the main thread, lock C1 Lock(C1) {//call a method that is not lockC1. Donotlockme (); //call the Lock method and attempt to dismiss the deadlockC1. Lockme (false); } } }
The program runs as shown in the results. In the T1 thread, Lockme calls lock (this), which is the C1 in the main function, when you call Lock (C1) in the main thread, you must wait for the lock block in T1 to complete before you can access C1, that is, all C1-related operations cannot be completed. So we see even C1. None of the Donotlockme () has been executed.
Let's change the C1 code slightly, and the code inside the Mian () main function remains the same:
classC1 {Private BOOLdeadlocked =true; Private ObjectLocker =New Object(); //This method uses lock, and we want lock's code to be accessible only by one thread at a time Public voidLockme (Objecto) {Lock(locker) { while(deadlocked) {deadlocked= (BOOL) O; Console.WriteLine ("foo:i am Locked:("); Thread.Sleep ( -); } } } //methods that all threads can access concurrently Public voidDonotlockme () {Console.WriteLine ("I am not locked:)"); } }
The program runs as shown in the results. This time we use a private member as the lock variable (locker), and in Lockme we only lock the private locker, not the entire object. At this time rerun the program, you can see that although T1 deadlock, Donotlockme () can still be accessed by the main thread, Lockme () is still inaccessible, because the locked locker has not been released by T1.
Key points:
1. The disadvantage of lock (this) is that after a thread (for example, T1) locks an object by executing a method of that class using "lock" (for example, Lockme () of this example), the entire object cannot be accessed by another thread (for example, the main thread of this example)- This is because many people use lock (c1)-like code when using the class in other threads, such as the main thread of this example.
2. Locking is not just the code in the lock segment, the lock itself is thread -safe.
3. We should use private objects that do not affect other operations as locker.
4. When using lock, the lock object (locker) must be a reference type, if it is a value type, will cause the object to be boxed into a new reference object each time lock is used (in fact, if you use a value type, the C # compiler (3.5.30729.1) An error will be given at compile time).
The value types of C # include: struct (numeric type, bool type, user-defined struct), enumeration, nullable type. The reference types of C # include: arrays, user-defined classes, interfaces, delegates, object, strings.
Therefore, if you have the following definitions:
Class A
{
}
struct S
{
}
int i;
Object o;
String str;
A a=new a ();
s s=new s ();
Please note that the following syntax is correct or an error is indicated.
Lock (i) {}//error
Lock (o) {}//correct
Lock (str) {}//correct
Lock (a) {}//correct
Lock (s) {}//error
The lock statement uses Monitor.Enter and monitor.exit at all, which means that lock (this) executes Monitor.Enter (this) and the curly brace executes monitor.exit (this) at the end. What does he mean by that, for any object, he puts the address of all the methods in the first part of the memory, and the second part is an index that points to a syncblock in the SyncBlock cache area of the CLR. What does that mean? When you execute Monitor.Enter (object), if the index value of object is negative, a syncblock from the SyncBlock cache is placed in the index of the object. This completes the lock with the object flag, and the other threads want to do the Monitor.Enter (object) operation again, get an index with an object positive, and then wait. Until the index becomes negative, that is, the thread uses Monitor.Exit (object) to make the index negative.
system.threading.monitor.enter (x); Try { ...} finally { system.threading.monitor.exit (x);}
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 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.
Other reference connections:
Http://www.jb51.net/article/57220.htm
Http://www.2cto.com/kf/201110/108043.html
Http://www.csharpwin.com/csharpspace/12362r6119.shtml
Understanding the lock syntax meaning of C #