Multithreading should try to avoid synchronization problems, it is best not to share data between THREADS. If you have to share data, you need to use synchronization technology to ensure that only one thread at a time accesses and alters the shared State.
a:: lock Statement
The lock statement is a simple way to set locking and contact Locking. The syntax is simple:
Lock (obj) { // code area where synchronization needs to occur }
Put the operation code of the shared data in the "{...}" above Area. The locked object (obj) must be a reference type, and if a value type is locked, it actually locks a copy of it and does not implement the lock Function.
In general, a locked object needs to be created as a private read-only reference type:
Private ReadOnly Object New Object ();
ii:: Interlocked class
The Interlocked class is used to atomically make a simple statement of a variable. It provides a way to increment, decrement, swap, and read values in a thread-safe manner.
Private intStateflag =0; public intIncrementstate {//Get//{ //Lock (this)// { //stateflag++; //return stateflag; // } //} Get { returnInterlocked.Increment (refstateflag);//using system.threading; //interlocked.decrement (ref V0); //interlocked.exchange (ref V1, ref V2); //interlocked.read (ref V0); } }
three:: Monitor Class
Similar to lock, C # 's lock statement is parsed by the compiler to use the monitor class. Locking starts the equivalent of the Monitor.Enter (obj) method, which waits until the thread is locked by the Object. After unlocking the thread into the synchronization phase and unlocking it using the Monitor.Exit (obj) method, the compiler binds it to the finally of the try Block. The code in method one is equivalent to:
monitor.enter (obj); Try { // code area for synchronization to occur } finally { Monitor.Exit (obj); }
The advantage of the monitor class compared to the lock statement is that you can add a timeout that waits for a North Lock. This will not wait indefinitely to be locked, but you can use the TryEnter () method to give a timeout parameter.
BOOLLockTaken =false; Monitor.TryEnter (obj, -,reflockTaken); if(lockTaken) {Try { //acquired the lock//synchronized region for obj } finally{monitor.exit (obj); } } Else { //didn ' t get the lock,do something else}
If obj is locked, the TryEnter () method sets the bool reference parameter LockTaken to True and synchronously accesses the state locked by obj. If another thread locks obj for more than 500 milliseconds, the Try Enter () method sets the variable LockTaken to false, and the thread no longer waits, but is used to perform other operations. Perhaps after that, the thread tries to be locked Again.
four:: spinlock Structure
It is a struct (struct) that is very similar to the monitor class. Gets the lock with the Enter () or TryEnter () method, releasing the lock with the Exit () method. It also provides properties Isheld and isheldbycurrentthred, specifying whether the current is Locked.
SpinLock Mspinlock =NewSpinLock ();//better just use a SpinLock . public voidfun1 () {// ..... BOOLLockTaken =false; Mspinlock.enter (reflockTaken); Try { //synchronized region } finally{mspinlock.exit (); } // ... } public voidfun2 () {// ..... BOOLLockTaken =false; Mspinlock.tryenter ( -,reflockTaken); if(lockTaken) {Try { //synchronized region } finally{mspinlock.exit (); } } Else { //didn ' t get the lock,do something else } // ...}
The spinlock structure is new to. Net 4. It is suitable for: there are a large number of locks, and the locking time is very short. The program needs to avoid using multiple SpinLock structures, and do not invoke any content that might be blocked.
v:: WaitHandle base class
WaitHandle is an abstract base class that is used to wait for a signal to be set. You can wait for different signals, because WaitHandle is a base class from which you can derive some Classes.
public Delegate intTakesawhiledelegate (intDataintms);//declaring a delegate public voidMain () {takesawhiledelegate vtawdl=takesawhile; IAsyncResult VAr= Vtawdl.begininvoke (1, the,NULL,NULL); while(true) {console.write ("."); if(vAr.AsyncWaitHandle.WaitOne ( -,false))//wait for Var.asyncwaithandle to receive signal (timeout 300 Milliseconds){console.writeline ("Can Get the result now."); break; } } intresult =Vtawdl.endinvoke (vAr); Console.WriteLine ("result:{0}", result);
Console.read (); } intTakesawhile (intDataintMs) {console.writeline ("Takesawhile started"); Thread.Sleep (ms); Console.WriteLine ("Takesawhile completed"); return++data; }
The above instance code, using the "asynchronous delegate", BeginInvoke () method returns an object that implements the Iasycresult Interface. Using the Iasycresult interface, you can access the WaitHandle base class with the Asycresult Property. When the WaitOne () method is called, the thread waits for a signal that is related to the wait Handle.
Use the WaitHandle class to wait for a signal to appear (the WaitOne () method), to wait for multiple objects that must be signaled (the WaitAll () method), or to wait for one of several objects (the WaitAny () method). After the two things WaitHandle the static method of the class, receive an array of WaitHandle Parameters.
vi:: Mutex class
A mutex (mutual exclusion, Mutex) is a class in The. NET framework that provides synchronous access across multiple processes . therefore, It is often used for "program single-boot control".
/// <summary> ///a single process check, if a process has been run, returns false, indicating that the check does not pass. otherwise, returns True. /// </summary> /// <returns></returns> Private BOOLRunoncecheck () {BOOLvexist; Mutex Nmutex=NewMutex (false,"Singletonwinappmutex", outvexist); if(!Vexist) { //indicates that one has been started and should exit the current boot return false; } return true; }
It is very similar to the Monitor class because they have only one thread that can have a lock. Only one thread can obtain a mutex lock and access the zone of the synchronized code protected by the Mutex. The mutex derives from the base class waithandle, so the WaitOne () method can be used to obtain the mutex lock, which becomes the owner of the mutex in the Process. Call the ReleaseMutex () method to release the Mutex.
BOOLcreatednew; Mutex Mutex=NewMutex (false,"Procsharpmutex", outcreatednew); if(mutex. WaitOne ()) {Try { //synchronized region } finally{mutex.} ReleaseMutex (); } } Else { //some problem happened while waiting}
seven:: Semaphore class
Semaphore is very similar to mutexes, except that semaphore can be used by multiple threads at the same time. It is a count mutex lock that defines the number of threads that allow simultaneous access to resources that are protected by their locks. It applies to: There are many resources available, and only a certain number of threads are allowed to access the Resource.
Viii.: Events Category
It is a way to synchronize resources within the system Scope.
nine:: Barrier Class
It is well suited for situations in which there are many task branches in which work is required and later need to be merged.
ten:: ReaderWriterLockSlim Class
You can use this class in order for the locking mechanism to allow multiple readers to be locked (rather than a writer) to access a resource. It provides a locking feature that allows multiple readers to access a resource without a writer locking the resource, but only one writer can lock the Resource.
C # multi-thread thread synchronization