Multithreading programming learning notes-thread synchronization (3), multithreading programming learning notes
Multi-thread programming learning notes-thread synchronization (1) connection multi-thread programming learning notes-thread synchronization (2)
7. Use the Barrier class
The Barrier class is used to organize multiple threads to meet in a timely manner. It provides a callback function. This callback function is executed every time the thread calls the SignalAndWait method.
1. The Code is as follows:
Using System; using System. collections. generic; using System. linq; using System. text; using System. threading; // introduce the thread using System. diagnostics; namespace ThreadSynchronousDemo {class Program {static Barrier barr = new Barrier (2, B => Console. writeLine ("End of stage {0}", B. currentPhaseNumber + 1); static void Main (string [] args) {Console. writeLine ("START, Barrier synchronization"); var t = new Thread () => working ("Thread 1", "1st Worker Thread Tasks ", 3); var t2 = new Thread () => working (" Thread 2 "," 2nd worker Thread Tasks ", 6); t. start (); t2.Start (); Console. read ();} static void working (string name, string message, int seconds) {for (int I = 0; I <3; I ++) {Console. writeLine ("-------- work phase -------------"); Thread. sleep (TimeSpan. fromSeconds (seconds); Console. writeLine ("{0} started working, content: {1}", name, message); Thread. sleep (TimeSpan. fromSeconds (seconds )); Total working time of Console. WriteLine ("{0} {1 }. End of work, {2} ", name, seconds, message); barr. SignalAndWait ();}}}}
2. Running result. For example.
A Barrier instance is created, specifying the two threads to be synchronized. After either of the two threads calls the SignalAndWait method, the callback function is called to display the current stage. This class is very useful in multi-threaded Iterative Computing. You can execute some operations before each iteration ends. When the last thread calls the SignalAndWait method, it interacts before the iteration ends.
8. Use ReaderWriteLockSlim class
ReaderWriteLockSlim represents a lock for managing resource access. It allows multiple threads to read data at the same time, but is exclusively written.
1. The Code is as follows.
Using System; using System. collections. generic; using System. linq; using System. text; using System. threading; // introduce the thread using System. diagnostics; namespace ThreadSynchronousDemo {class Program {static ReaderWriterLockSlim rws = new ReaderWriterLockSlim (); static List <int> list = new List <int> (); static void Main (string [] args) {Console. writeLine ("START, ReaderWriterLockSlim synchronization"); var t = new Thread (Read) {I SBackground = true}; var t2 = new Thread (Read) {IsBackground = true}; var t3 = new Thread (Read) {IsBackground = true }; var t4 = new Thread () => Write ("Thread 1") {IsBackground = true}; var t5 = new Thread ((() => Write ("thread 2") {IsBackground = true}; // read data thread t. start (); t2.Start (); t3.Start (); // write data thread t4.Start (); t5.Start (); Console. read ();} static void Read () {Console. writeLine ("------- -Read data from the List ------------- "); while (true) {try {rws. enterReadLock (); foreach (var item in list) {Console. writeLine ("read data content: {0}", item); Thread. sleep (TimeSpan. fromSeconds (1) ;}} catch (Exception ex) {throw ex;} finally {rws. exitReadLock () ;}} static void Write (string threadName) {Console. writeLine ("-------- write data to List -------------"); while (true) {try {int newInt = new Random (). next (1, 1 00); rws. EnterUpgradeableReadLock (); if (! List. contains (newInt) {// if the data is not in the List, write try {rws. enterWriteLock (); list. add (newInt); Console. writeLine ("{0} written data content: {1}", threadName, newInt);} finally {rws. exitWriteLock ();} Thread. sleep (TimeSpan. fromSeconds (1) ;}} catch (Exception ex) {throw ex;} finally {rws. exitUpgradeableReadLock ();}}}}}
2. Run the program running result and send it.
After the program starts, it runs five threads directly. Three of the threads read data from the collection, and the two threads write data to the collection.
The read lock allows multiple threads to read data at the same time. The write lock blocks all other threads before being released. When the thread acquires the read lock and reads data from the set, it also determines whether there is a write lock in the current set to write data. If there is a write lock, it will block the thread from reading data, this will waste time. Therefore, in this example, the EnterUpgradeabledReadLock and ExitUpgradeabledReadLock methods are used to obtain the read lock and then read the data. If you want to modify the data in the Set, upgrade the lock to ReaderWriterLock and write the data, finally, use ExitWriteLock to exit the lock.
9. Use the SpinWait class
SpinWait is a hybrid synchronization structure, that is, waiting for a while in user mode, and then switching to kernel mode to save CPU time.
1. The Code is as follows:
Using System; using System. collections. generic; using System. linq; using System. text; using System. threading; // introduce the thread using System. diagnostics; namespace ThreadSynchronousDemo {class Program {static volatile bool isCompleted = false; static void Main (string [] args) {Console. writeLine ("START, SpinWait synchronization"); var t = new Thread (UserModeWait); var t2 = new Thread (HybirdSpinWait); Console. writeLine ("Start, Run user mode "); T. start (); Thread. sleep (50); isCompleted = true; Thread. sleep (TimeSpan. fromSeconds (5); isCompleted = false; Console. writeLine ("Start, Run kernel mode"); t2.Start (); Thread. sleep (TimeSpan. fromSeconds (5); isCompleted = true; Console. read ();} static void UserModeWait () {Console. writeLine ("-------- user mode wait -------------"); while (! IsCompleted) {Console. Write (". "); Thread. sleep (TimeSpan. fromSeconds (1);} Console. writeLine (); Console. writeLine ("user mode awaiting completion");} static void HybirdSpinWait () {var spin = new SpinWait (); Console. writeLine ("-------- Kernel Mode -------------"); while (! IsCompleted) {spin. spinOnce (); // NextSpinWillYield: determines whether the thread that calls the SpinOnce method should let out the CPU Console. writeLine ("whether to let out the CPU: {0}", spin. nextSpinWillYield);} Console. writeLine ("kernel mode ended ");}}}
2. The program running result is shown in figure 2 below.
In the program, we have a thread that executes an infinite loop. After 50 ms, the main thread sets isCompleted to true. We can view the CPU load in windows Resource Manager.