C#任务同步
using System; using System.Diagnostics; using System.Threading; using System.Threading.Tasks; using static System.Console; //任务同步 //1.lock 锁定一个引用类型的变量 /*死锁 lock (_s1) { lock (_s2) {} } lock (_s2) { lock (_s1) {} } */ //2.Interlocked类,更快但只支持少数几种的操作 //public int State //{ // get // { // lock (this) // { // return ++_state; // } // } //} //相当于 //public int State //{ // get // { // return Interlocked.Increment(ref _state); // } //} //3.Monitor类 //4.SpinLock结构,传递时需加引用,不然结构会以值传递 // 如果有大量锁定,如列表的每一个节点都有一个锁定,且锁定时间非常短,SpinLock结构就很有用 // 它与Monitor类似,Enter TryEnter Exit //5.WaitHandle 抽象基类 用于等待一个信号(WaitOne() WaitAll() ...) //6.Mutex类 操作系统能识别有名称的互斥,可以跨线程,如果没有指定名称则不在不同的进程之间共享 //7.Semaphore类 非常类似于互斥,区别是它可以同时由多个线程使用,是一种计数的互斥 //8.Event类 事件与互斥和信号量一样,也是一个系统范围内的资源同步方法 // ManualResetEvent AutoResetEvent ManualResetEventSlim CountdownEvent //9.Barrier类 ReaderWriterLockSlim类 //10.Timer类 // Threading中的Timer 基于XAML应用程序的DispatcherTimer namespace ConsoleApp { public class StateObject { private int _state = 5; private object _sync = new object(); public void ChangeState(int loop) { lock (_sync)//方法2. { if (_state == 5) { _state++; Trace.Assert(_state == 6, $"Race condition occured after {loop} loops"); } _state = 5; } } } class Program { static void Main(string[] args) { //RaceCondition(); object o = new object(); lock (o) { } //lock由编译器解析为Monitor类 Monitor.Enter(o); try { } finally { Monitor.Exit(o); } //Monitor可以设置等待时间 bool _lockTaken = false; Monitor.TryEnter(o, 500, ref _lockTaken); if (_lockTaken)//get the lock { try { } finally { Monitor.Exit(o); } } else { } //互斥 bool createNew; //第3个为输出参数,接收一个表示互斥是否为新建的布尔值, //如果(createNew)返回为false就表示互斥已经定义 var mutex = new Mutex(false, "ProCSharpMutex", out createNew); if (mutex.WaitOne()) { try { } finally { mutex.ReleaseMutex(); } } else { //some problem happened while waiting } //信号量 int taskCount = 6; int semaphoreCount = 3; var semaphore = new Semaphore(semaphoreCount-1, semaphoreCount);//初始请求数 最大请求数 try { int preCount = semaphore.Release(); WriteLine($"preCount: {preCount}"); } catch (Exception) { } var tasks = new Task[taskCount]; for (int i = 0; i < taskCount; ++i) { tasks[i] = Task.Run(() => TaskMain(semaphore)); } Task.WaitAll(tasks); WriteLine("All tasks finished"); //事件 AutoResetEvent autoEvent = new AutoResetEvent(false); autoEvent.Reset(); autoEvent.Set(); autoEvent.WaitOne(); //Timer using (var timer1 = new Timer(TimeAction, null, 0/*TimeSpan.FromSeconds(0)*/, 1000/*TimeSpan.FromSeconds(3)*/)) { Task.Delay(15000).Wait(); } ReadKey(); } public static void RaceCondition() { var state = new StateObject(); //开启2个Task for (int i = 0; i < 2; ++i) { Task.Run(() => { int j = 0; while (true) { lock (state)//方法1. { state.ChangeState(j++); } } }); } } public static void TaskMain(Semaphore semaphore) { bool isComplete = false; while(!isComplete) { if (semaphore.WaitOne(50))//等到 计数-1 { try { WriteLine($"Task {Task.CurrentId} locks the semaphore"); Task.Delay(200).Wait(); } finally { WriteLine($"Task {Task.CurrentId} release the semaphore"); semaphore.Release(); //释放 计数+1 isComplete = true; } } else { WriteLine($"Timeoue for task {Task.CurrentId}; wait again"); } } } private static void TimeAction(object o) { WriteLine($"System.Threading.Timer {DateTime.Now:T}"); } } }