C#執行緒間同步的幾種實現方式
阿新 • • 發佈:2019-01-08
一、使用訊號量
using System; using System.Threading; namespace SemaphoreDemo { class Program { static void Main(string[] args) { for(int i = 0; i <= 6; i++) { string threadName = "thread " + i; int secondsToWait = 2 + 2 * i; var t = new Thread(() => AccessDatabase(threadName, secondsToWait)); t.Start(); } Console.ReadKey(); } //可同時有四個資源可訪問 static SemaphoreSlim _semaphore = new SemaphoreSlim(4); static void AccessDatabase(string name, int seconds) { Console.WriteLine("{0} waits to access a database", name); _semaphore.Wait(); Console.WriteLine("{0} was granted an access to a database", name); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("{0} is completed", name); _semaphore.Release(); } } }
二、使用AutoResetEvent
using System; using System.Threading; namespace AutoResetEventDemo { class Program { static void Main(string[] args) { var t = new Thread(() => Process(10)); t.Start(); Console.WriteLine("waiting for another thread to complete work"); _workerEvent.WaitOne(); Console.WriteLine("first operation is completed!"); Console.WriteLine("performing an operation on a main thread"); Thread.Sleep(TimeSpan.FromSeconds(5)); _mainEvent.Set(); Console.WriteLine("now running the second operation on a second thread"); _workerEvent.WaitOne(); Console.WriteLine("second operation is completed!"); Console.ReadKey(); } private static AutoResetEvent _workerEvent = new AutoResetEvent(false); private static AutoResetEvent _mainEvent = new AutoResetEvent(false); static void Process(int seconds) { Console.WriteLine("starting a long running work..."); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("work is done!"); _workerEvent.Set(); Console.WriteLine("waiting for a main thread to complete its work"); _mainEvent.WaitOne(); Console.WriteLine("starting second operation..."); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("work is done!"); _workerEvent.Set(); } } }
三、使用ManualResetEvent
using System; using System.Threading; namespace ManualResetEventSlimDemo { class Program { static void Main(string[] args) { var t1 = new Thread(() => TravelThroughGates("thread 1", 5)); var t2 = new Thread(() => TravelThroughGates("thread 2", 5)); var t3 = new Thread(() => TravelThroughGates("thread 3", 5)); t1.Start(); t2.Start(); t3.Start(); Thread.Sleep(TimeSpan.FromSeconds(6)); Console.WriteLine("the gates are now open!"); _mainEvent.Set(); Thread.Sleep(TimeSpan.FromSeconds(2)); _mainEvent.Reset(); Console.WriteLine("the gates have been closed!"); Thread.Sleep(TimeSpan.FromSeconds(10)); Console.WriteLine("the gates are now open for the second time!"); _mainEvent.Set(); Thread.Sleep(TimeSpan.FromSeconds(2)); Console.WriteLine("the gate have been closed!"); _mainEvent.Reset(); Console.ReadKey(); } static ManualResetEventSlim _mainEvent = new ManualResetEventSlim(false); static void TravelThroughGates(string threadName, int seconds) { Console.WriteLine("{0} fails to sleep", threadName); Thread.Sleep(TimeSpan.FromSeconds(seconds)); Console.WriteLine("{0} waits for the gates to open!", threadName); _mainEvent.Wait(); Console.WriteLine("{0} enters the gates!", threadName); } } }
四、使用CountDownEvent
using System;
using System.Threading;
namespace CountDownEventDemo
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("starting two operations");
var t1 = new Thread(() => PerformOperation("operation 1 is completed", 4));
var t2 = new Thread(() => PerformOperation("operation 2 is completed", 8));
t1.Start();
t2.Start();
//等待所有訊號量返回
//如果沒有Signal()返回,將永久性等待;或可使用帶時間引數方式等待
_countdown.Wait();
Console.WriteLine("both operation have been completed");
_countdown.Dispose();
Console.ReadKey();
}
//計數為2
static CountdownEvent _countdown = new CountdownEvent(2);
static void PerformOperation(string message, int seconds)
{
Thread.Sleep(TimeSpan.FromSeconds(seconds));
Console.WriteLine(message);
//返回訊號
_countdown.Signal();
}
}
}