Multithreading in. NET (use semaphores for synchronization) and. net Multithreading

Source: Internet
Author: User

Multithreading in. NET (use semaphores for synchronization) and. net Multithreading

The previous section describes how to use a lock for synchronization. This section describes how to use a semaphore for synchronization.

Use EventWaitHandle semaphores for synchronization

EventWaitHandle is mainly used to implement the traffic signal mechanism. The signal light is mainly used to notify the waiting thread. There are two main implementations: AutoResetEvent and ManualResetEvent.

AutoResetEvent

AutoResetEvent is literally an automatic reset time. For example, if there are many people waiting outside the door, AutoResetEvent is more like a cross revolving door, each time only one person is allowed to enter, the door is still closed after entering.

The following example demonstrates the usage:

Using System; using System. threading; class BasicWaitHandle {static EventWaitHandle _ waitHandle = new AutoResetEvent (false); static void Main () {for (int I = 0; I <3; I ++) new Thread (Waiter ). start (); for (int I = 0; I <3; I ++) {Thread. sleep (1000); // Pause for a second... console. writeLine ("notifies the next thread to enter"); _ waitHandle. set (); // Wake up the Waiter .} console. readLine ();} static void Waiter () {var threadId = Thread. currentThread. managedThreadId; Console. writeLine ("thread {0} is waiting", threadId); _ waitHandle. waitOne (); // wait for the notification Console. writeLine ("thread {0} is notified, you can enter", threadId );}}

  

Bidirectional signal lamp

In some cases, if you repeatedly use the Set method to notify the worker thread, the worker thread may not be ready to receive signals at this time, in this case, the subsequent Set notifications may be ineffective. In this case, you need to let the main thread get a notification from the worker thread to receive information and then start sending information. You may need two signal lights to implement this function.

Sample Code:

Using System; using System. threading; class TwoWaySignaling {static EventWaitHandle _ ready = new AutoResetEvent (false); static EventWaitHandle _ go = new AutoResetEvent (false); static readonly object _ locker = new object (); static string _ message; static void Main () {new Thread (Work ). start (); _ ready. waitOne (); // wait for lock (_ locker) _ message = "Moonlight before bed"; _ go. set (); // notifies the worker thread to start working _ ready. W AitOne (); lock (_ locker) _ message = "suspected ground cream"; _ go. set (); _ ready. waitOne (); lock (_ locker) _ message = "end"; // tell the worker thread to exit _ go. set (); Console. readLine ();} static void Work () {while (true) {_ ready. set (); // indicates that the current thread is ready to receive the signal _ go. waitOne (); // The Working thread waits for the notification lock (_ locker) {if (_ message = "end") return; // elegantly exits ~ -~ Console. WriteLine (_ message );}}}}
Production and Consumption queue

Production and Consumption queues are common requirements in multi-thread programming. Their main ideas are as follows:

Sample Code:

using System;using System.Threading;using System.Collections.Generic; class ProducerConsumerQueue : IDisposable{  EventWaitHandle _wh = new AutoResetEvent (false);  Thread _worker;  readonly object _locker = new object();  Queue<string> _tasks = new Queue<string>();   public ProducerConsumerQueue()  {    _worker = new Thread (Work);    _worker.Start();  }   public void EnqueueTask (string task)  {    lock (_locker) _tasks.Enqueue (task);    _wh.Set();  }   public void Dispose()  {    EnqueueTask (null);     // Signal the consumer to exit.    _worker.Join();         // Wait for the consumer's thread to finish.    _wh.Close();            // Release any OS resources.  }   void Work()  {    while (true)    {      string task = null;      lock (_locker)        if (_tasks.Count > 0)        {          task = _tasks.Dequeue();          if (task == null) return;        }      if (task != null)      {        Console.WriteLine ("Performing task: " + task);        Thread.Sleep (1000);  // simulate work...      }      else        _wh.WaitOne();         // No more tasks - wait for a signal    }  }}

To ensure thread security, we use lock to protect the Queue <string> set. We also show that WaitHandle is disabled.

In. NET 4.0, a new BlockingCollection class implements functions similar to producer and consumer queues.

ManualResetEvent

ManualResetEvent is literally an event that needs to be closed manually. For example, if there are many people waiting outside the door, it is like a common door. After the door is opened, all the people waiting outside the door can come in. When you close the door, people outside are no longer allowed to come in.

Sample Code:

Using System; using System. threading; class BasicWaitHandle {static EventWaitHandle _ waitHandle = new ManualResetEvent (false); static void Main () {for (int I = 0; I <3; I ++) new Thread (Waiter ). start (); Thread. sleep (1000); // Pause for a second... console. writeLine ("the door is opened and the thread enters"); _ waitHandle. set (); // Wake up the Waiter. new Thread (Waiter ). start (); Thread. sleep (2000); _ waitHandle. reset (); Console. writeLine ("doors closed, Thread blocking"); new Thread (Waiter ). start (); Console. readLine ();} static void Waiter () {var threadId = Thread. currentThread. managedThreadId; Console. writeLine ("thread {0} is waiting", threadId); _ waitHandle. waitOne (); // wait for the notification Console. writeLine ("thread {0} is notified, you can enter", threadId );}}

ManualResetEvent can wake up all the waiting threads in the current thread. This application is very important.

CountdownEvent

CountdownEvent is opposite to ManualEvent. Multiple Threads wake up one thread together.

Sample Code:

 

Using System; using System. threading; class CountDownTest {static CountdownEvent _ countdown = new CountdownEvent (3); static void Main () {new Thread (SaySomething ). start ("I am thread 1"); new Thread (SaySomething ). start ("I am thread 2"); new Thread (SaySomething ). start ("I am thread 3"); _ countdown. wait (); // The current thread is blocked until the Console receives the three signals sent by _ countdown. writeLine ("All threads have finished speaking! "); Console. readLine ();} static void SaySomething (object thing) {Thread. sleep (1, 1000); Console. writeLine (thing); _ countdown. signal ();}}
Create an EventWaitHandle across processes

The EventWaitHandle constructor allows you to create a named EventWaitHandle to implement cross-process semaphore operations. The name is just a simple string, as long as it does not conflict with the locks of other processes.

Sample Code:

EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset, "MyCompany.MyApp.SomeName");

  

If the two processes run this code, the semaphore will act on all the threads in the two processes.

 

This section describes how to use signals for thread synchronization. The next section describes non-blocking synchronization.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.