. NET Component Programming thread and concurrency Management (2)

Source: Internet
Author: User
Tags lock queue

. Net Component Programming thread and concurrency Management (2)

2. Synchronization thread
  • Manual synchronization
    • Monitor
    • Mutual Exclusion
    • Event waiting

 

Synchronization thread

All. the. NET component supports running in a multi-threaded environment and can be accessed by multiple threads concurrently. If there is no thread synchronization, the consequence is that when multiple threads simultaneously access the object status, the object state may be damaged, causing inconsistency .. NET provides two methods to avoid such problems, making the components we designed more robust. The first is automatic synchronization, which allows you to modify components by using an attribute. In this way, you can hand over the components to. NET, and the synchronization tasks will be handed over to. NET. The second is manual synchronization, which is not too complicated for you to use the synchronization objects provided by. NET to implement thread synchronization. This article will explain manual synchronization in a bit.

 

2.1 manual synchronization

. NET manual synchronization provides a rich set of synchronization locks. When talking about synchronization domains in the previous section, synchronization domains are actually a huge macro lock, manual synchronization provides fine-grained control over the locked object, allowing you to control the code for accessing the object, a single member, or even a single row. The advantage is that it is possible to improve the system performance and throughput.

2.1.1 Monitor

A monitor is a lock that can only work with the reference type.

2.1.1-1

 1     public class ManualSynchronization 2     { 3         public void DoSomeThing() 4         { 5             for (int i = 0; i < 100; i++) 6             { 7                 Console.WriteLine(i.ToString()); 8             } 9         }10     }
 1 ManualSynchronization monitorcase = new ManualSynchronization(); 2  3 Monitor.Enter(monitorcase); 4 try 5 { 6     monitorcase.DoSomeThing(); 7 } 8 finally 9 {10     Monitor.Exit(monitorcase);11 }

Any object in any thread can call the Enter () method to lock the object. If the Monitor is being used by a thread, another thread requests the object Enter (), in this way, the second thread will be blocked until the first thread calls Exit (). If multiple threads request the object Enter (), they will be placed in a queue called lock queue and get the service order in the queue order.

You can also use the Monitor class to provide secure thread access for static class methods or static attributes by locking the Monitor type instead of an instance:

2.1.1-2

 1     public class ManualSynchronization 2     { 3         public static void SDoSomeThing() 4         { 5             for (int i = 0; i < 100; i++) 6             { 7                 Console.WriteLine(i.ToString()); 8             } 9         }10     }
1            Monitor.Enter(typeof(ManualSynchronization));2            try3            {4                ManualSynchronization.SDoSomeThing();5            }6            finally7            {8                Monitor.Exit(typeof(ManualSynchronization));9            }

In C #, a lock statement is provided for the compiler to automatically generate a call to Enter () and Exit () in a try/finally statement.

For example, if you write this code, it is equivalent to the sample code 2.1.1-1:

2.1.1-3

1 ManualSynchronization monitorcase = new ManualSynchronization();2 lock(monitorcase)3 {4     monitorcase.DoSomeThing();5 } 

Writing like the code above seems no problem, because the instance or object type specified by the lock depends on the judgment of the client developer, this locking method is highly coupled with the client. See the following code:

2.1.1-4

 1     public class ManualSynchronization 2     { 3         public void DoSomeThing() 4         { 5             lock (this) 6             { 7                 for (int i = 0; i < 100; i++) 8                 { 9                     Console.WriteLine(i.ToString());10                 }11             }12         }13     }
1 ManualSynchronization monitorcase = new ManualSynchronization();2 monitorcase.DoSomeThing();

It feels quite comfortable. This is the method for synchronization ,. NET is also supported internally, defined in System. runtime. the MethodImpl method attribute in the CompilerServices namespace accepts an enumeration of the MethodImplOptions type. One of the enumerated values is MethodImplOptions. Synchronized. When you run this enumeration value, the editor instructs. NET to lock the object at the method entry during runtime. The semantics is the same as that of the 2.1.1-4 Code:

2.1.1-5

1     public class ManualSynchronization2     {3         [MethodImpl( MethodImplOptions.Synchronized)]4         public void DoSomeThingSynchroniezd()5         {6             Console.WriteLine("studycase");7         }8     } 
2.1.2 mutex

This section describes the Mutex class, which is derived from WaitHandle and ensures that each thread is mutually exclusive on a resource or code block.

2.1.2-1

 1     public class MutexDom:IDisposable 2     { 3         public MutexDom(){} 4         private int _Num = 0; 5         public int Num 6         { 7             get 8             { 9                 return _Num;10             }11             set12             {13                 _Num = value;14             }15         }16         public void Dom()17         {18                  for (int i = 0; i < 100; i++)19                 {20                     Num = Num + i;21                     Console.WriteLine(Thread.CurrentThread.Name + "_" + Num.ToString() +"_"+Thread.CurrentThread.ManagedThreadId.ToString());22                 }23 24             25         }26         public void Dispose()27         {28          29         }30 31         public static void Test()32         {33             MutexDom mutexDom=new MutexDom();34             ThreadStart threadStart=new ThreadStart(mutexDom.Dom);35             Thread thread1 = new Thread(threadStart);36             thread1.Name = "Thread_One";37             Thread thread2 = new Thread(threadStart);38             thread2.Name = "Thread_Two";39             thread1.Start();40             thread2.Start();41         }42     }

MutexDom. test (); start the Test. The expected result is that the Dom () method is executed in an orderly manner, and I use an int type Nun attribute as the counter, let's take a look at the results (the results may be different each time)

What does this mean when I want to execute 0 in the Thread_One thread to increase the value of 99 to 4950, and the result is beyond this range? It indicates that the two threads are alternately operating on Num. Modify the code and take a look at it again:

2.1.2-2

1 public class MutexDom: IDisposable 2 {3 private Mutex _ Mutex; 4 public MutexDom () 5 {6 _ Mutex = new Mutex (); 7} 8 private int _ Num = 0; 9 public int Num10 {11 get12 {13 return _ Num; 14} 15 set16 {17 _ Num = value; 18} 19} 20 public void Dom () 21 {22 _ Mutex. waitOne (); // if the current resource is occupied, wait for the thread occupying it to send the message 23 try24 {25 for (int I = 0; I <100; I ++) 26 {27 Num = Num + I; 28 Console. writeLine (Thread. currentThread. name + "_" + Num. toString () + "_" + Thread. currentThread. managedThreadId. toString (); 29} 30} 31 finally32 {33 _ Mutex. releaseMutex (); 34} 35 36} 37 public void Dispose () 38 {39 _ Mutex. close (); 40} 41 42 public static void Test () 43 {44 MutexDom mutexDom = new MutexDom (); 45 ThreadStart threadStart = new ThreadStart (mutexDom. dom); 46 Thread thread1 = new Thread (threadStart); 47 thread1.Name = "Thread_One"; 48 Thread thread2 = new Thread (threadStart); 49 thread2.Name = "Thread_Two "; 50 51 thread1.Start (); 52 thread2.Start (); 53 54} 55}

It is obtained from the result that the thread Thread_Two executes the statement first. It does not matter. You only need to check the result value. This shows that the thread "Thread_Two" executes the Dom () during method operations, "Thread_One" must have been started and is waiting for the release message of "Thread_Two". In this way, the object state is consistent, "Thread_One" is in a waiting queue. If "Thread_One" calls the ReleaseMutex () method at this time, an error is returned, because the ReleaseMutex () method can only be released by the currently occupied threads, and mutual exclusion is completed.

2.1.3 event waiting

The EventWaitHandle class is derived from WaitHandle and used to notify events across threads. It has two States: the signal has been sent, and the signal has not been sent. The Set () method and Reset () method respectively Set the handle status to signal sent or not sent. It can be used either manually or automatically. Is to provide the constructor with an enumerated value of the EventResetMode type,

1     public enum EventResetMode2     {3        AutoReset,4        ManualReset5     }

. NET provides two strongly-typed subclasses of EventWaitHandle, which are defined as follows:

 1     public class ManualResetEvent:EventWaitHandle 2     { 3         public ManualResetEvent(bool initialState):base(initialState,EventResetMode.ManualReset) 4         {} 5     } 6     public sealed class AutoResetEvent : EventWaitHandle 7     { 8         public AutoResetEvent(bool initialState):base(initialState,EventResetMode.AutoReset) 9         {}10     }

Let's take a look at manual resetting:

2.1.3-1

 1     public class EventDom:IDisposable 2     { 3         ManualResetEvent _WaitHandle; 4         public EventDom() 5         { 6             _WaitHandle = new ManualResetEvent(true); 7  8             Thread thread = new Thread(DoWork); 9             thread.Start();10         }11         private void DoWork()12         {13             int num = 0;14             while (true)15             {16                 _WaitHandle.WaitOne();17                 num++;18                 Console.WriteLine("EventDom_" + num.ToString());19             }20         }21         public void StartThread()22         {23             _WaitHandle.Set();24             Console.WriteLine("EventDom->StartThread");25         }26         public void StopThread()27         {28             _WaitHandle.Reset();29             Console.WriteLine("EventDom->StopThread");30         }31         public void Dispose()32         {33             _WaitHandle.Close();34         }35 36         public static void Test()37         {38             EventDom eventDom = new EventDom();39             eventDom.StopThread();40         }41 42      }

Call EventDom. Test (); To Test the function. The result is as follows:

In the constructor, I have declared the manual reset event as a signal sending State. Therefore, when running, while waiting for the received signal during each loop is always in the sent state, therefore, the execution is paused until the Reset () method in the StopThread () method is called and the status is set to not sent.

Let's take a look at automatic resetting and modify the code in the previous section,

 1     public class EventDom : IDisposable 2     { 3         AutoResetEvent _WaitHandle; 4         public EventDom() 5         { 6             _WaitHandle = new AutoResetEvent(true); 7  8             Thread thread = new Thread(DoWork); 9             thread.Start();10         }11         private void DoWork()12         {13             int num = 0;14             while (true)15             {16                 _WaitHandle.WaitOne();17                 num++;18                 Console.WriteLine("EventDom_" + num.ToString());19             }20         }21         public void StartThread()22         {23             _WaitHandle.Set();24             Console.WriteLine("EventDom->StartThread");25         }26         public void StopThread()27         {28             _WaitHandle.Reset();29             Console.WriteLine("EventDom->StopThread");30         }31         public void Dispose()32         {33             _WaitHandle.Close();34         }35 36         public static void Test()37         {38             EventDom eventDom = new EventDom();39             eventDom.StartThread();40         }41     }

First, replace the manual resetting type with the automatic resetting type, and then test the code to change the method of setting the status to not sent to the method of setting the status to sent.

This result is correct, because the automatic reset type is that the event state is set to the signal has been sent, and it will remain in this state until a thread is released from the pending call, and then at this time, its status will change and it will automatically reverse to the unsent status.

I hope this article will be helpful to you. END

 

 

 

Author: Jin Yuan

Source: http://www.cnblogs.com/jin-yuan/

The copyright of this article is shared by the author and the blog Park. You are welcome to reprint this article. However, you must keep this statement without the author's consent and go to the Article Page.

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.