volatile keyword
Volatile is the simplest method of synchronization, and of course, it's a price to pay. It can only be synchronized at the variable level, the meaning of volatile is to tell the processor, do not put me into the working memory, please directly in main memory operation me. ("www.bitsCN.com") therefore, when multithreading accesses the variable at the same time, it will manipulate the main memory directly and do the variable sharing in essence.
The number of types that can be identified as volatile must be the following: (excerpt from MSDN)
Any reference type.
Any pointer type (under an unsafe context).
The types sbyte, Byte, short, ushort, int, uint, char, float, bool.
An enum type with a enum base type of Byte, SByte, short, ushort, int, or UINT.
Lock keyword
Lock is a simple and easy way to synchronize threads by acquiring mutexes for a given object. It ensures that when a thread is in a critical section of code, another thread does not come in, it waits until the thread object is freed, that is, the thread is out of the critical section. Usage:
The parameter of lock must be based on the reference type of the object, not the basic type like bool,int, so it is not synchronous at all, because the parameters of lock is the object, if the incoming int, it is bound to take place boxing operation, so each lock will be a new different object. It is best to avoid using the public type or an object instance that is not controlled by the program because it is likely to cause deadlocks. In particular, do not use a string as a parameter to lock because the string is "persisted" by the CLR, meaning that there is only one instance of the string given in the entire application, so it is more likely to cause deadlocks. It is recommended that you use a private or protected member that is not "persisted" as a parameter. In fact, some classes have already provided dedicated members to be locked, such as the array type provides SyncRoot, and many other collection types also provide syncroot.
Therefore, use lock should pay attention to the following points:
1, if the instance of a class is public, it is best not to lock (this). Because the person who uses your class may not know that you are using lock, and if he has a new instance, and locks the instance, it can easily cause a deadlock.
2, if the MyType is public, do not lock (typeof (MyType))
3. Never lock a string
Monitor
The Monitor class provides functionality similar to lock, but unlike lock, it has better control over the synchronization block, and when the Enter (object o) method of Monitor is called, the exclusive right of O is obtained until the exit (object O) method is called. To release exclusive rights to O, you can call the Enter (object o) method multiple times, just call the same number of exit (object O) methods, and the Monitor class provides an overloaded method of TryEnter (object O,[int]). This method attempts to acquire the exclusive rights of an O object, and returns false when the acquisition of exclusive rights fails.
However, using lock is generally preferable to using Monitor directly, on the one hand because lock is more concise and, on the other hand, because lock ensures that the underlying monitor can be released even if the protected code throws an exception. This is done by calling exit in finally. In fact, lock is implemented using the Monitor class. The following two sections of code are equivalent:
Code lock (x){DoSomething();} 等效于object obj = ( object )x;System.Threading.Monitor.Enter(obj);try {DoSomething();}finally {System.Threading.Monitor.Exit(obj);}
MethodImplAttribute
If the code inside the entire method needs to be locked, it would be easier to use the MethodImplAttribute property. So you don't have to lock inside the method, just add [MethodImpl (methodimploptions.synchronized)] on the method, Both Mehthodimpl and methodimploptions are inside the namespace System.Runtime.CompilerServices. Note, however, that this property locks the entire method until the method returns, releasing the lock. So the use is not very flexible. If you want to release the lock early, you should use monitor or lock. Let's look at an example:
Code[methodimpl (methodimploptions.synchronized)]public void Dosomeworksync () {Console.WriteLine (" Dosomeworksync ()--lock held by Thread "+ Thread.CurrentThread.GetHashCode ()); Thread.Sleep (1000); Console.WriteLine ("Dosomeworksync ()--lock released by Thread" + Thread.CurrentThread.GetHashCode ());} public void Dosomeworknosync () {Console.WriteLine ("Dosomeworknosync ()--entered Thread is" + Thread.CurrentThread.GetH Ashcode ()); Thread.Sleep (1000); Console.WriteLine ("Dosomeworknosync ()--leaving Thread is" + Thread.CurrentThread.GetHashCode ());} [Stathread]static void Main (string [] args) {methodimplattr testobj = new Methodimplattr (); thread T1 = new Thread (new ThreadStart (Testobj.dosomeworknosync)); Thread t2 = new Thread (new ThreadStart (Testobj.dosomeworknosync)); T1. Start (); T2. Start (); thread t3 = new Thread (new ThreadStart (Testobj.dosomeworksync)); thread T4 = new Thread (new ThreadStart (Testobj.dosomeworksync)); T3. Start (); T4. Start (); Console.ReadLine ();}
Here, we have two methods, we can compare, one is to add the attribute MethodImpl Dosomeworksync (), one is not added Dosomeworknosync (). Sleep (1000) in the method is intended to allow enough time for the second thread to come in when the first thread is still in the method. Starting with two threads for each method, let's take a look at the results:
As you can see, for threads 1 and 2, that is, the thread that calls the method without attributes, when thread 2 enters the method, has not left, thread 1 has come in, that is, the method is not synchronized. Let's take a look at threads 3 and 4, when thread 3 comes in, the method is locked until thread 3 releases the lock, and thread 4 comes in.
C # thread synchronization