C # various Synchronization Methods: lock, Monitor, Mutex, Semaphore, Interlocked, ReaderWriterLock, AutoResetEvent, ManualResetEvent,

Source: Internet
Author: User

C # various Synchronization Methods: lock, Monitor, Mutex, Semaphore, Interlocked, ReaderWriterLock, AutoResetEvent, ManualResetEvent,

Take a look at the organizational structure:

System. Object
System. externalbyrefobject
System. Threading. WaitHandle
System. Threading. Mutex
System. Threading. Semaphore
System. Threading. EventWaitHandle
System. Threading. ManualResetEvent

System. Threading. AutoResetEvent

 

System. Object

System. Threading. Interlocked
System. Threading. Monitor

System. Threading. ReaderWriterLock

 

1. The lock keyword is actually encapsulation of the Enter () and Exit () Methods of the Monitor class. Use the try... catch... finally statement block to ensure that the Monitor. Exit () method is executed after the lock statement block is complete to release the mutex lock. The following two sections of code are equivalent:

lock(locker){  //do something}
View Code

 

Monitor.Enter(locker);try{    // do something}finally{    Monitor.Exit(locker);}
View Code

 

2,

The Monitor class grants an object lock to a single thread to control access to the object. Object locks provide the ability to restrict access to critical zones. When a thread has an object lock, no other thread can obtain the lock. You can also use Monitor to ensure that no other thread is allowed to access the application code section being executed by the lock owner, unless another thread is using another lock object to execute the code. Through the analysis of the lock keyword, we know that lock is an encapsulation of the Enter and Exit of Monitor, and it is more concise to use. Therefore, the Enter () and Exit () of the Monitor class () the combination of methods can be replaced by the lock keyword.
Common Methods of the Monitor class:
TryEnter ():
It can effectively solve problems such as long-term crashes. If TryEnter is used in an environment where a concurrency occurs frequently and lasts for a long time, it can effectively prevent deadlocks or long waits. For example, you can set a waiting time bool gotLock = Monitor. TryEnter (myobject, 1000) so that the current thread can decide whether to continue the following operations based on the returned bool value after waiting for 1000 seconds.

Wait ():

Release the lock on the object to allow other threads to lock and access the object. When other threads access an object, the calling thread will wait. The pulse signal is used to notify the waiting thread of changes to the object state.
Pulse ():
PulseAll ():
Sends signals to one or more waiting threads. This signal indicates that the status of the waiting thread lock object has changed, and the lock owner is ready to release the lock. Wait for the thread to be placed in the ready queue of the object so that it can finally receive the object lock. Once the thread has a lock, it can check the new State of the object to see if it has reached the desired state. Note: The Pulse, PulseAll, and Wait methods must be called from the synchronized code block.

Static object locker = new object (); static bool isHave = false; static void Produce () {lock (locker) {while (true) {// if a product already exists, then wait until the consumption is completed if (isHave) Monitor. wait (locker); Console. writeLine ("produce one"); Thread. sleep (1000); isHave = true; Monitor. pulse (locker) ;}} static void Consume () {lock (locker) {while (true) {// if no product exists, wait until production is complete if (! IsHave) Monitor. Wait (locker); Console. WriteLine ("consume one"); Thread. Sleep (500); isHave = false; Monitor. Pulse (locker );}}}
View Code

Call in the main function:

            new Thread(Produce).Start();            new Thread(Consume).Start();
View Code

 

3. Mutex

public class Test    {        // Create a new Mutex. The creating thread does not own the        // Mutex.        private static Mutex mut = new Mutex();        public static void MyThreadProc()        {            for (int i = 0; i < 2; i++)            {                UseResource();            }        }        // This method represents a resource that must be synchronized        // so that only one thread at a time can enter.        private static void UseResource()        {            // Wait until it is safe to enter.            mut.WaitOne();            Console.WriteLine("{0} has entered the protected area",                Thread.CurrentThread.Name);            // Place code to access non-reentrant resources here.            // Simulate some work.            Thread.Sleep(500);            Console.WriteLine("{0} is leaving the protected area\r\n",                Thread.CurrentThread.Name);            // Release the Mutex.            mut.ReleaseMutex();        }    }
View Code
Test test = new Test();            for (int i = 0; i < 3; i++)            {                Thread myThread = new Thread(new ThreadStart(Test.MyThreadProc));                myThread.Name = String.Format("Thread{0}", i + 1);                myThread.Start();            }
View Code

Mutex can also determine whether a process already exists in the system.

 

4. Semaphore

static Semaphore sph = new Semaphore(0, 3);        static void TProc()        {            while (true)            {                if (sph.WaitOne(500, false))                {                    try                    {                        Console.WriteLine("thread" + Thread.CurrentThread.Name + ":enter");                        Thread.Sleep(1000);                    }                    finally                    {                        sph.Release();                        Console.WriteLine("thread" + Thread.CurrentThread.Name + ":exit");                    }                }                else                {                    Console.WriteLine("thread" + Thread.CurrentThread.Name + ":time out");                }            }        }
View Code
Thread t = null;            for (int i = 0; i < 2; i++)            {                t = new Thread(TProc);                t.Name = i.ToString();                t.Start();            }            Console.WriteLine("main sleep 4s");            Thread.Sleep(4000);            sph.Release(2);
View Code

 

5. The Interlocker class provides atomic operations for variables shared by multiple threads. It is a static class and its main member methods are as follows:
Add: in the form of an atomic operation, Add two integers and replace the first integer with the sum of the two.
Exchange: sets the variable as the specified value in the form of an atomic operation, and returns the previous value
CompareExchange: compare whether two values are equal. If they are equal, replace one of the values.
Equals: Determine whether two Object instances are equal
Increment: increments the value of a specified variable in the form of an atomic operation and stores the result.
Decrement: Decrement the value of the specified variable in the form of an atomic operation and store the result.
Read: returns a 64-bit value loaded as an atomic operation.

Interlocked.CompareExchange(ref obj, new object(), null);
View Code

 

6. ReaderWriterLock

static ReaderWriterLock rwLock = new ReaderWriterLock();static object locker = new object();static void Main(string[] args){    Thread t = null;    for(int i = 0; i < 2;i++)    {        t = newThread(Writer);        t.Name =i.ToString();        t.Start();    }    for(int i = 0; i<3;i++)    {        t = newThread(Reader);        t.Name =i.ToString();        t.Start();    }    Console.ReadLine();}static void Writer(){    while(true)    {        try        {            rwLock.AcquireWriterLock(3000);            Console.WriteLine("writer:"+ Thread.CurrentThread.Name + " is enter" + "WriterSeqNum:" +rwLock.WriterSeqNum.ToString());            try            {                Thread.Sleep(5000);            }            finally            {                rwLock.ReleaseWriterLock();                Console.WriteLine("writer:"+ Thread.CurrentThread.Name + " is exit");            }        }        catch(ApplicationException)        {            Console.WriteLine("writer:"+ Thread.CurrentThread.Name + " wait time out");        }    }}static void Reader(){    while (true)    {        rwLock.AcquireReaderLock(-1);        Console.WriteLine("reader:"+ Thread.CurrentThread.Name + " is enter" + "WriterSeqNum:" +rwLock.WriterSeqNum.ToString());        try        {            Thread.Sleep(3000);        }        finally        {            Console.WriteLine("reader:"+ Thread.CurrentThread.Name + " is exit");            rwLock.ReleaseReaderLock();        }    }}
View Code

 

7. AutoResetEvent automatically resets the event

When constructing an event object, you must specify whether the initialState parameter is True or False to indicate whether the initial state of the event has a signal or no signal.

When an automatic reset event gets a signal, only one thread in the thread waiting for the event changes to a schedulable thread. When the manual reset object gets a signal, all threads waiting for this event become schedulable threads

 

class Example{    private static AutoResetEvent event_1 = new AutoResetEvent(true);    private static AutoResetEvent event_2 = new AutoResetEvent(false);    static void Main()    {        Console.WriteLine("Press Enter to create three threads and start them.\r\n" +                          "The threads wait on AutoResetEvent #1, which was created\r\n" +                          "in the signaled state, so the first thread is released.\r\n" +                          "This puts AutoResetEvent #1 into the unsignaled state.");        Console.ReadLine();        for (int i = 1; i < 4; i++)        {            Thread t = new Thread(ThreadProc);            t.Name = "Thread_" + i;            t.Start();        }        Thread.Sleep(250);        for (int i = 0; i < 2; i++)        {            Console.WriteLine("Press Enter to release another thread.");            Console.ReadLine();            event_1.Set();            Thread.Sleep(250);        }        Console.WriteLine("\r\nAll threads are now waiting on AutoResetEvent #2.");        for (int i = 0; i < 3; i++)        {            Console.WriteLine("Press Enter to release a thread.");            Console.ReadLine();            event_2.Set();            Thread.Sleep(250);        }        // Visual Studio: Uncomment the following line.        //Console.Readline();    }    static void ThreadProc()    {        string name = Thread.CurrentThread.Name;        Console.WriteLine("{0} waits on AutoResetEvent #1.", name);        event_1.WaitOne();        Console.WriteLine("{0} is released from AutoResetEvent #1.", name);        Console.WriteLine("{0} waits on AutoResetEvent #2.", name);        event_2.WaitOne();        Console.WriteLine("{0} is released from AutoResetEvent #2.", name);        Console.WriteLine("{0} ends.", name);    }}
View Code

 

8. ManualResetEvent manual reset event

public class Example{    // mre is used to block and release threads manually. It is    // created in the unsignaled state.    private static ManualResetEvent mre = new ManualResetEvent(false);    static void Main()    {        Console.WriteLine("\nStart 3 named threads that block on a ManualResetEvent:\n");        for(int i = 0; i <= 2; i++)        {            Thread t = new Thread(ThreadProc);            t.Name = "Thread_" + i;            t.Start();        }        Thread.Sleep(500);        Console.WriteLine("\nWhen all three threads have started, press Enter to call Set()" +                          "\nto release all the threads.\n");        Console.ReadLine();        mre.Set();        Thread.Sleep(500);        Console.WriteLine("\nWhen a ManualResetEvent is signaled, threads that call WaitOne()" +                          "\ndo not block. Press Enter to show this.\n");        Console.ReadLine();        for(int i = 3; i <= 4; i++)        {            Thread t = new Thread(ThreadProc);            t.Name = "Thread_" + i;            t.Start();        }        Thread.Sleep(500);        Console.WriteLine("\nPress Enter to call Reset(), so that threads once again block" +                          "\nwhen they call WaitOne().\n");        Console.ReadLine();        mre.Reset();        // Start a thread that waits on the ManualResetEvent.        Thread t5 = new Thread(ThreadProc);        t5.Name = "Thread_5";        t5.Start();        Thread.Sleep(500);        Console.WriteLine("\nPress Enter to call Set() and conclude the demo.");        Console.ReadLine();        mre.Set();        // If you run this example in Visual Studio, uncomment the following line:        //Console.ReadLine();    }    private static void ThreadProc()    {        string name = Thread.CurrentThread.Name;        Console.WriteLine(name + " starts and calls mre.WaitOne()");        mre.WaitOne();        Console.WriteLine(name + " ends.");    }}
View Code

 

9. In some collection classes, such as Queue, ArrayList, HashTable, and Stack,. NET already provides an object SyncRoot for lock.

Queue q = new Queue();                 lock (q.SyncRoot)                 {                     foreach (object item in q)                     {                         //do something                     }                 }  
View Code

 

References: http://blog.csdn.net/zzy7075/article/details/29842165

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.