Elaborate. NET multithreading (five uses semaphores for synchronization)

Source: Internet
Author: User
Tags semaphore

The previous section mainly describes the use of locks for synchronization, this section mainly describes the use of semaphores to synchronize

Synchronizing with EventWaitHandle semaphores

EventWaitHandle is mainly used to implement the signaling mechanism. Beacons are primarily used to notify waiting threads. There are two main implementations: AutoResetEvent and ManualResetEvent.

AutoResetEvent

AutoResetEvent is literally a time to reset automatically. For example, suppose there are a lot of people waiting outside the door, AutoResetEvent more like a cross-revolving door, each time only allow one person to enter, after entering the door is still closed.

The following example shows how to use:

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 (+);                  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 notification        Console.WriteLine ("Thread {0} to be notified, can enter", threadId);}    }

  

Bidirectional Beacon

In some cases, if you use the Set method repeatedly to notify the worker thread, the worker thread may not be ready to receive the signal at this time, so a few subsequent set notifications may not be effective. In this case, you need to let the main thread get a notification that the worker is receiving the message and start sending the message. You may need to implement this function with two lights.

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 until the worker is ready to receive the message lock (_locker) _message = "Moon light Before Bed"; _go.                         Set (); Notifies the worker that the work thread has started working _ready.        WaitOne ();        Lock (_locker) _message = "Suspicion is ground frost"; _go.        Set (); _ready.        WaitOne ();    Lock (_locker) _message = "End"; Tells the worker to exit _go.        Set ();    Console.ReadLine (); } static void Work () {while (true) {_ready.                          Set (); Indicates that the current thread is ready to receive signal _go.                         WaitOne ();        Worker thread waits for notification lock (_locker) {if (_message = = "End") return; Graceful Exit ~-~ CoNsole.            WriteLine (_message); }        }    }}
Production consumption queue

The production and consumption queue is a common requirement in multithreaded programming, and his main ideas are:

    1. A queue to hold the data that the worker needs to use
    2. When a new task joins the queue, the calling thread does not have to wait for the work to end
    3. 1 or more worker threads get data information in the queue in the background

Example 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 (); The 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 safety, we use lock to protect the Queue<string> collection. We also showed off the WaitHandle.

In. NET 4.0, a new class BlockingCollection implements a function similar to that of a producer consumer queue.

ManualResetEvent

ManualResetEvent is literally an event that needs to be closed manually. For example: Suppose there are a lot of people waiting outside the door, it is like an ordinary door, after the door opened, all the people waiting outside the door can come in, when you close the door, no longer allow outside people to come in.

Example 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 (+);                  Pause for a second        ... Console.WriteLine ("Door is open, Thread enters");        _waithandle.set ();                    Wake up the waiter.        New Thread (Waiter). Start ();        Thread.Sleep (+);        _waithandle.reset ();        Console.WriteLine ("Door closed, Thread blocked");        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 notification        Console.WriteLine ("Thread {0} to be notified, can enter", threadId);}    }

ManualResetEvent can wake up all the waiting threads in the current thread, which is very important.

Countdownevent

The use of countdownevent is the opposite of manualevent, where multiple threads collectively wake up a thread.

Example 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 it receives the three signals sent by _countdown        Console.WriteLine ("All Threads has finished speaking!");        Console.ReadLine ();    }    static void SaySomething (Object thing)    {        thread.sleep (+);        Console.WriteLine (thing);        _countdown. Signal ();    }}
Create a eventwaithandle across processes

EventWaitHandle's construction method allows the creation of a named EventWaitHandle to implement semaphore operations across processes. The name is just a simple string, as long as it is guaranteed not to conflict with other process locks.

Example code:

EventWaitHandle WH = new EventWaitHandle (False, Eventresetmode.autoreset, "MyCompany.MyApp.SomeName");

  

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

This section describes the use of signals for thread synchronization, and the next section describes non-blocking synchronizations.

Elaborate. NET multithreading (five uses semaphores for synchronization)

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.