Multithreading (thread synchronization 1), multithreading thread synchronization 1

Source: Internet
Author: User

Multithreading (thread synchronization 1), multithreading thread synchronization 1

In multithreading (thread synchronization), we will learn how to operate on shared resources in multithreading. The learned knowledge points are as follows:

  • Perform basic atomic operations
  • Construct with Mutex
  • Construct with SemaphoreSlim
  • Construct with AutoResetEvent
  • Use ManualResetEventSlim to construct
  • Use CountDownEvent to construct
  • Construct with Barrier
  • Construct with ReaderWriterLockSlim
  • Construct with SpinWait

1. Perform basic atomic operations

In this section, we will learn how to avoid the occurrence of blocking threads, execute basic atomic operations on an object and prevent the occurrence of race condition. The procedure is as follows:

1. Use Visual Studio 2015 to create a new console application.

2. Double-click to open the "Program. cs" file and write the code as follows:

 1 using System; 2 using System.Threading; 3 using static System.Console; 4  5 namespace Recipe01 6 { 7     abstract class CounterBase 8     { 9         public abstract void Increment();10 11         public abstract void Decrement();12     }13 14     class Counter : CounterBase15     {16         private int count;17 18         public int Count => count;19 20         public override void Increment()21         {22             count++;23         }24 25         public override void Decrement()26         {27             count--;28         }29     }30 31     class CounterNoLock : CounterBase32     {33         private int count;34 35         public int Count => count;36 37         public override void Increment()38         {39             Interlocked.Increment(ref count);40         }41 42         public override void Decrement()43         {44             Interlocked.Decrement(ref count);45         }46     }47 48     class Program49     {50         static void TestCounter(CounterBase c)51         {52             for (int i = 0; i < 100000; i++)53             {54                 c.Increment();55                 c.Decrement();56             }57         }58 59         static void Main(string[] args)60         {61             WriteLine("Incorrect counter");62 63             var c1 = new Counter();64 65             var t1 = new Thread(() => TestCounter(c1));66             var t2 = new Thread(() => TestCounter(c1));67             var t3 = new Thread(() => TestCounter(c1));68             t1.Start();69             t2.Start();70             t3.Start();71             t1.Join();72             t2.Join();73             t3.Join();74 75             WriteLine($"Total count: {c1.Count}");76             WriteLine("--------------------------");77 78             WriteLine("Correct counter");79 80             var c2 = new CounterNoLock();81 82             t1 = new Thread(() => TestCounter(c2));83             t2 = new Thread(() => TestCounter(c2));84             t3 = new Thread(() => TestCounter(c2));85             t1.Start();86             t2.Start();87             t3.Start();88             t1.Join();89             t2.Join();90             t3.Join();91 92             WriteLine($"Total count: {c2.Count}");93         }94     }95 }

3. Run the console application. The running effect may be different each time, as shown in:

In the code of Row 3, we created a non-thread-safe Counter Class Object c1. Because it is non-thread-safe, race condition occurs ).

In 65th ~ In 67 lines of code, we created three threads to run the "TestCounter" method of the c1 object. In this method, we perform auto-increment and auto-increment operations on the count variable of the c1 object in order. Because c1 is NOT thread-safe, in this case, the counter value we get is uncertain. We can get 0, but run it several times more, in most cases, the error result is not 0.

In multithreading (basic), we use the lock keyword to lock the object to solve this problem, but using the lock keyword will cause blocking of other threads. However, in this example, we do not use the lock keyword, but use Interlocked to construct it. It provides Increment and Decrement for basic mathematical operations) and other methods.

2. construct with Mutex

In this section, we will learn how to use Mutex to construct two separate programs to synchronize processes. The procedure is as follows:

1. Use Visual Studio 2015 to create a new console application.

2. Double-click to open the "Program. cs" file and write the code as follows:

1 using System; 2 using System. threading; 3 using static System. console; 4 5 namespace Recipe02 6 {7 class Program 8 {9 static void Main (string [] args) 10 {11 const string MutexName = "Multithreading "; 12 13 using (var m = new Mutex (false, MutexName) 14 {15 // The WaitOne method is used to stop the current thread until it receives the processing signal released by other instances. 16 // The first parameter is the wait time-out time, and the second parameter is whether to exit the context synchronization domain. 17 if (! M. WaitOne (TimeSpan. FromSeconds (10), false) 18 {19 WriteLine ("Second instance is running! "); 20 ReadLine (); 21} 22 else23 {24 WriteLine (" Running! "); 25 ReadLine (); 26 // release mutex resource 27 m. ReleaseMutex (); 28} 29} 30 31 ReadLine (); 32} 33} 34}

3. Compile the code and run the program twice. The running effect is as follows:

Result of the first case:

Result of the second case:

At line 1 of the code, we defined a mutex (Mutex) name as "Multithreading" and passed it to the mutex class constructor at line 3 of the Code, the first initialOwner of the constructor is assigned false, which allows the program to obtain a mutex that has been created. If no thread locks the mutex resource, the program simply displays "Running" and waits for any key to release the mutex resource.

If we start the second instance of the program, if we did not press any button under the first instance within 10 seconds to release the mutex resource, in the Second instance, "Second instance is running!" is displayed! ", The result is shown in the first case. If we press any key in the first instance within 10 to release the mutex resource, "Running" is displayed in the second instance, as shown in the Running result in the second case.

3. construct with SemaphoreSlim

In this section, we will learn how to limit the number of threads simultaneously accessing resources with the help of SemaphoreSlim construction. The procedure is as follows:

1. Use Visual Studio 2015 to create a new console application.

2. Double-click to open the "Program. cs" file and write the code as follows:

 1 using System; 2 using System.Threading; 3 using static System.Console; 4 using static System.Threading.Thread; 5  6 namespace Recipe03 7 { 8     class Program 9     {10         static SemaphoreSlim semaphore = new SemaphoreSlim(4);11 12         static void AccessDatabase(string name, int seconds)13         {14             WriteLine($"{name} waits to access a database");15             semaphore.Wait();16             WriteLine($"{name} was granted an access to a database");17             Sleep(TimeSpan.FromSeconds(seconds));18             WriteLine($"{name} is completed");19             semaphore.Release();20         }21 22         static void Main(string[] args)23         {24             for(int i = 1; i <= 6; i++)25             {26                 string threadName = "Thread" + i;27                 int secondsToWait = 2 + 2 * i;28                 var t = new Thread(() => AccessDatabase(threadName, secondsToWait));29                 t.Start();30             }31         }32     }33 }

3. Run the console application. The running effect may be different each time, as shown in:

 

At line 1 of the code, we created a SemaphoreSlim instance and passed parameter 4 to the constructor. This parameter specifies how many threads can access resources at the same time. Then we started six threads with different names. Every thread tries to obtain access to the database. However, we limit that only four threads can access the database. Therefore, after four threads access the database, the other two threads must wait until other threads finish their work and call the "Release" method to Release resources before they can access the database.

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.