. net advanced level 06 async asynchronous, thread multithread 4


Knowledge needs to be accumulated, summarized and precipitated. Thinking and writing are the catalysts for growth


I. lock1、lock2、Interlocked3、Monitor4、SpinLock5、Mutex6、Semaphore7、Events1、AutoResetEvent2、ManualResetEvent3、ManualResetEventSlim8、ReaderWriterLock2、 Thread safe collection3、 Multithreading model1. Synchronous programming model SPM2. Asynchronous programming model APM3. EAP based on event programming model4. Tap based on task programming modelFour, End

I. lock

There are also lock concepts in the database. Row lock, table lock, object lock, etc. the function of lock isSecurity consistency of data under control of concurrency, so that when one data is operated, other concurrent threads wait. In the development aspect, when multithreaded parallel programming accesses shared data, in order to ensure the consistent security of data, sometimes locks are needed to lock objects to achieve synchronization

Many thread synchronization technologies are available in. Net. Lock, interlocked, monitor, etc. are used for in-process synchronization lock, mutex mutex, semaphore semaphore, events, readerwriterlockslim read-write lock, etc. are used for thread synchronization among multiple processes


Lock statement is a simple way to set lock and unlock, and it is also the most commonly used synchronization method. Lock is used to lock aReference type fieldWhen the thread executes to lock, the field will be locked, so that only one thread enters the lock statement block, and then the lock will be released at the end of the lock statement, and another thread can enter. Principle using synchronous block index, interested can study the following

lock (obj){    //synchronized region}

Because only one thread can enter, and there is no concurrency, performance is sacrificed, so try toNarrow the scope of lock, another suggestion is to prefer to lock a private variable, that isSyncroot mode, declare a private object variable of syncroot to lock instead of using lock (this). Because the external caller may also lock the instance of your object, but he does not know that you also use lock internally, so it is easy to cause deadlock

Private object syscroot = new object(); public void dothis() {lock (syscroot) {// only one thread can reach here at the same time}}}


Interloaded is used to atomize some simple operations of variables, that is, thread safe synchronization. The I + + we often write is not thread safe. Take a value from memory and put it back in memory. It is likely to be interrupted by other threads in the process. For example, when you put it back in memory after + 1, the other thread has put it back first, and it is not synchronized. The innerlocked class providesThread safe ways of increasing, decreasing, exchanging and reading values
For example, the following is an incremental way to replace lock

int num = 0;//lock (syscRoot)//{//    num++;//}num = Interlocked.Increment(ref num);


The above lock is the syntax sugar of monitor, and the code of monitor will be generated through compiler compilation, like the following

Lock (syscroot) {// synchronized region} // the lock above is equivalent to the following monitormonitor.enter (syscroot); try {// synchronized region} finally {monitor. Exit (syscroot);}

Monitor is different from lock in that it can also set the time-out time without unlimited waiting.

bool lockTaken = false;Monitor.TryEnter(syscRoot,500,ref lockTaken);if (lockTaken){    try    {        //synchronized region    }    finally    {        Monitor.Exit(syscRoot);    }}else{}


Spinlock is a user mode lock. By the way, put in a wordLocks are divided into kernel mode locks and user mode locksThe kernel mode is to interrupt the thread at the system level, and then switch back to work when receiving the signal. The user mode is to let the thread run until it is available through some CPU specified or dead cycle. Each has its own advantages and disadvantages. The resource utilization of CPU in the kernel is high, but the switching loss is the opposite of the user mode. If the locking time is long, it will wait in a white circle. Then there will be mixed mode locks

If there are a large number of locks, and the lock time is very short, spinlock is very useful. Its usage is similar to monitor. Enter or tryenter obtains the lock, and exit releases the lock. Isheld and isheldbycurrentthread specify whether it is currently locked

In addition, spinlock is a structure type, so pay attention to the problem of creating new copies when assigning copies. Pass by reference if necessary


Mutex mutex provides to synchronize a class across multiple processes. When defining mutex, you can specify the name of mutex, so that the system can recognize it. Therefore, mutex defined in another process can be accessed by other processes, and mutex. Openexisting() can get it.

bool createdNew = false;Mutex mutex = new Mutex(false, "ProCharpMutex", out createdNew);if (mutex.WaitOne()){    try    {        //synchronized region    }    finally    {        mutex.ReleaseMutex();    }}

In this case, we can disable an application to start twice. Generally, we judge by the name of the process. Here we use mutex to implement

Bool creatednew = false; mutex mutex = new mutex (false, "Singleton winappmutex", out creatednew); if (! Creatednew) {messagebox.show ("application has been started"); application. Exit(); return;}


Semaphore semaphore semaphore is similar to mutually exclusive semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphore semaphoreMultiple threads using, is a count of mutually exclusive locks. Count allows several threads to access protected resources at the same time. You can also specify semaphore names to share among multiple processes

Semaphore and the mutex above are inherited from the waithandle base class. Waithandle is used to wait for a signal setting. When waithandle is used, the thread will wait to receive a signal related to the waiting handle

Semaphoreslim is a lightweight alternative to semaphore (it does not inherit waithandle), semaphoreslim (int initialcount, Int maxcount) constructor can specify the maximum concurrent number, and then wait through semaphoreslim’s wait in the thread to receive the signal whether it can enter the protected code block, and finally remember to release, otherwise the next thread can’t get the allowed signal


Event locks are different from events in delegates. Under the system.threading namespace, they are used to synchronize system wide event resources, including AutoResetEvent automatic event locks, manualresetevent manual event locks and lightweight version of manualreseteventslim


AutoResetEvent also inherits from waithandle class and waits until there is a signal through waitone. It has two states:Termination and non termination, you can call the set and reset methods to put the object into a terminated and non terminated state. The popular point is that there is a signal in set, another thread can enter, reset is not terminated without information, and other threads are blocked. Automatic means that one thread enters, and other threads cannot enter if there is no signal in the automatic reset setting. Similar to the real car toll gate, one pole one car mode

Private AutoResetEvent autoevent = new AutoResetEvent (false); public void dothis() {autoevent. Waitone(); // execute synchronization code block autoevent. Set();}

The difference between manual event lock and automatic event lock is that when there is no signal, a batch of threads will be blocked. When there is a signal, all threads will run and wake up multiple threads at the same time. Unless the manual reset is blocked again, it is similar to the fence at the railway crossing in the real scene, where a group of people are intercepted by dropping the pole and a group of people are swarming through the pole. The usage is the same as above. Waitone waits for the signal and knots Bundle time informs that there is a signal through set. It can pass


Manual reset event slim provides a hybrid lock mode of spin wait and kernel wait by encapsulating manual reset event. If you need to synchronize across processes or across AppDomains, you must use manualresetevent. Manualreseteventslim uses wait to block threads and supports task cancellation. Like semaphoreslim’s wait, internalSpin through user mode and then kernel mode is more efficient


The readerwriterlock is not to protect resources by limiting the number of threads, but by pressingReading and writing angleTo distinguish, you can lock that when one type of thread (write thread) enters the protected resource, the other type of thread (read thread) is blocked. If no write thread locks the resource, multiple read thread method resources are allowed, but only one write thread can lock the resource

Refer to examples for specific usage

//Create a read-write lockreaderwriterlock rwlock = new readerwriterlock(); // the current thread obtains a read lock. The parameters are: timeout value (MS) rwlock.acquirerlock (250); // judge whether the current thread holds a read lock if (! Rwlock. Isreaderlockheld) {return;} console. Writeline ("read lock obtained..."); // upgrade the read lock to a write lock. The lock parameters are: timeout Value (MS) lockcookie = rwlock. Upgradetowriterlock (250); // determine whether the current thread holds the write lock if (rwlock. Iswriterlockheld) {console. Writeline ("upgraded to write lock..."); // restore the lock to the previous level, that is, rwlock. Downgradefromwriterlock (Ref cookie);} // release the read lock (reduce the lock count, Until the count reaches zero, the lock is released) rwlock. Releasereaderlock(); console. Writeline ("successfully executed..."); // the current thread obtains the write lock, with the parameters as follows: timeout value (MS) rwlock. Acquiredwriterlock (250); // judge whether the current thread holds the write lock if (rwlock. Iswriterlockheld) {console. Writeline ("obtained the write lock..."); // release Write lock (the write lock count will be reduced until the count becomes zero, and the lock will be released) rwlock. Releasewriterlock();} // release the write lock (the write lock count will be reduced until the count becomes zero, and the lock will be released). // if the current thread does not hold the lock, an exception rwlock. Releasewriterlock(); console. Writeline ("successfully executed..."); console. Readline();

ReaderWriterLockSlimIt is also a lightweight optimized version of readerwriterlock, which simplifies the rules of recursion, upgrade and degradation of lock state.
1. Enterwritelock enters the write mode lock state
2. Enterreadlock enters the read mode lock state
3. EnterUpgradeableReadLock enters the upgradeable read mode lock state
And the three locking modes have timeout mechanism, corresponding to try Method, exit the corresponding mode using exit Methods, and all methods must be in pairs

2、 Thread safe collection

In order to ensure the security of resources, we usually use the lock or semaphore to solve this problem. In fact. Net also has some thread safe collections built in. Using them is like using single thread collections.

type describe
BlockingCollection Provides restriction and blocking capabilities for any type of implementation of iproducerconsumercollection. For more information, see blockingcollection overview.
ConcurrentDictionary Thread safe implementation of key / value pair dictionary.
ConcurrentQueue Thread safe implementation of FIFO queue.
ConcurrentStack Thread safe implementation of LIFO stack.
ConcurrentBag Thread safe implementation of an unordered collection of elements.
IProducerConsumerCollection Type must implement the interface to be used in blockingcollection.

3、 Multithreading model

1. Synchronous programming model SPM

2. Asynchronous programming model APM

Our commonXXBegin, XXEndThese two classic pairing methods are asynchronous. After begin, it will delegate to the thread pool to call a thread to execute. And the BeginInvoke call of the delegate

FileStream fs = new FileStream("D:\test.txt", FileMode.Open);var bytes = new byte[fs.Length];fs.BeginRead(bytes, 0, bytes.Length, (aysc) =>{    var num = fs.EndRead(aysc);}, string.Empty);

3. EAP based on event programming model

The backgroundworker class in winfrom / WPF development is an implementation scheme of asynchronous event mode. The runworkerasync method starts the method asynchronously associated with the dowork event. When the work is completed, the runworkercompleted event will be triggered. It also supports cancelaysnc method cancellation and reportprogress notification progress. Another typical example is webclient

WebClient client = new WebClient();client.DownloadDataCompleted += (sender,e)=> {};client.DownloadDataAsync(new Uri("https://www.baidu.com/"));

4. Tap based on task programming model

After the task came out, Microsoft vigorously promoted the asynchronous programming model based on task. APM and EAP were packaged as tasks. The following example simply encapsulates the above programming model with task. Webclient’s downloaddatataskasync implementation is similar to the example, using a taskcompletionsource wrapper to wrap a task

FileStream fs = new FileStream("D:\test.txt", FileMode.Open);var bytes = new byte[fs.Length];var task = Task.Factory.FromAsync(fs.BeginRead, fs.EndRead, bytes, 0, bytes.Length, string.Empty);var nums = task.Result;Action action = () =>{ };var task = Task.Factory.FromAsync(action.BeginInvoke, action.EndInvoke, string. Empty); public static task < int > gettaskasuc (string URL) {taskcompletionsource < int > source = new taskcompletionsource < int > (); // wrapper webclient client = new webclient(); client. Downloaddatacompleted + = (sender, e) = > {try {source. Trysetresult (e.resu lt.Length);        }        catch (Exception ex)        {            source.TrySetException(ex);        }    };    client.DownloadDataAsync(new Uri(url));    return source.Task;}

Four, End

Recent articles have shown you how to write multithreaded and multitasking applications. In the process of application development, we need to plan carefully. Too many threads lead to resource problems, and too few threads do not have a great effect. A pertinent suggestion in multithreaded programming is
Avoid modifying shared variables as much as possible to reduce synchronization requirements. Most of the synchronization complexity can be reduced by reasonable planning.

Search the fucking web
Read the fucking maunal


Recommended Today

The application of USB camera in rk3399

The application of USB camera in rk3399 1, introduction UVCFull nameUSB Video Class, is a set of standard customized by usb-if. All USB interface cameras complying with this standard can almost be used directly under Windows Linux and other systems, achieving the similar effect of drive free. Of course, it doesn’t mean that there is […]