This article describes the usage of mutually exclusive objects in C# multi-threaded learning. Share it for your reference. The specific analysis is as follows:
How to control the relationship between multiple threads without conflict or duplication, this requires the use of mutex objects, namely: Mutex class in the namespace.
We can think of Mutex as a taxi and passengers as threads. Passengers first wait for the car, then get on and finally get off. When a passenger is in the car, other passengers can only get on the car after they get off. This is the same between threads and Mutex objects. The thread uses the() method to wait for the Mutex object to be released. If the Mutex object it is waiting for is released, it will automatically own the object until it calls the() method to release the object. During this period, other threads that want to obtain the Mutex object can only wait.
The following example uses a Mutex object to synchronize four threads. The main thread waits for the end of the four threads, and the operation of these four threads is associated with two Mutex objects.
It also uses an object of the AutoResetEvent class, which can be understood as a signal light. Here it is used to indicate the end of a thread.
() method sets it to a signal state
() method sets it to signalless state
Example program of Mutex class:
using System; using ; namespace ThreadExample { public class MutexSample { static Mutex gM1; static Mutex gM2; const int ITERS = 100; static AutoResetEvent Event1 = new AutoResetEvent(false); static AutoResetEvent Event2 = new AutoResetEvent(false); static AutoResetEvent Event3 = new AutoResetEvent(false); static AutoResetEvent Event4 = new AutoResetEvent(false); public static void Main(String[] args) { ("Mutex Sample "); //Create a Mutex object and name it MyMutex gM1 = new Mutex(true,"MyMutex"); //Create an unnamed Mutex object. gM2 = new Mutex(true); (" - Main Owns gM1 and gM2"); AutoResetEvent[] evs = new AutoResetEvent[4]; evs[0] = Event1; //Define the AutoResetEvent object for the subsequent threads t1, t2, t3, t4, and t4. evs[1] = Event2; evs[2] = Event3; evs[3] = Event4; MutexSample tm = new MutexSample( ); Thread t1 = new Thread(new ThreadStart(tm.t1Start)); Thread t2 = new Thread(new ThreadStart(tm.t2Start)); Thread t3 = new Thread(new ThreadStart(tm.t3Start)); Thread t4 = new Thread(new ThreadStart(tm.t4Start)); ( ); //Use the() method to wait for all objects in a Mutex array to be released ( ); //Use() method to wait for gM1 to be released ( ); //Use the() method to wait for any object in a Mutex array to be released ( ); //Use() method to wait for gM2 to be released (2000); (" - Main releases gM1"); ( ); //The end condition of thread t2 and t3 is satisfied (1000); (" - Main releases gM2"); ( ); //The end condition of thread t1 and t4 is satisfied //Waiting for all four threads to end (evs); (" Mutex Sample"); (); } public void t1Start( ) { ("t1Start started, (Mutex[])"); Mutex[] gMs = new Mutex[2]; gMs[0] = gM1; //Create a Mutex array as a parameter of the() method gMs[1] = gM2; (gMs); //Waiting for both gM1 and gM2 to be released (2000); ("t1Start finished,(Mutex[]) satisfied"); ( ); //The thread ends, set Event1 to signaled state } public void t2Start( ) { ("t2Start started, ( )"); ( );//Waiting for the release of gM1 ("t2Start finished, ( ) satisfied"); ( );//The thread ends, set Event2 to signaled state } public void t3Start( ) { ("t3Start started, (Mutex[])"); Mutex[] gMs = new Mutex[2]; gMs[0] = gM1;//Create a Mutex array as a parameter of the() method gMs[1] = gM2; (gMs);//Waiting for any Mutex object in the array to be released ("t3Start finished, (Mutex[])"); ( );//The thread ends, set Event3 to signal state } public void t4Start( ) { ("t4Start started, ( )"); ( );//Waiting for gM2 to be released ("t4Start finished, ( )"); ( );//The thread ends, set Event4 to signal state } } }
The output result of the program:
Mutex Sample - Main Owns gM1 and gM2 t1Start started, (Mutex[]) t2Start started, ( ) t3Start started, (Mutex[]) t4Start started, ( ) - Main releases gM1 t2Start finished, ( ) satisfied t3Start finished, (Mutex[]) - Main releases gM2 t1Start finished, (Mutex[]) satisfied t4Start finished, ( ) Mutex Sample
From the execution results, it can be clearly seen that the operation of threads t2 and t3 is conditional on the release of gM1, and t4 starts execution after gM2 is released, and t1 is only executed after both gM1 and gM2 are released. Finally, the Main() function uses WaitHandle to wait for the signals of all AutoResetEvent objects, and the signals of these objects represent the end of the corresponding thread.
I hope this article will be helpful to everyone's C# programming.