标签:may 使用 dad attr out 特定 token 进程间 释放
#define CODE1 using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SomeDemo { public class AsyncDemo { public void Run() { MutexTest(); } /// <summary> /// 线程间同步, 可以暂时释放锁 /// TryEnter、Enter用于获取锁 /// Exit用于释放锁 /// Wait用于暂时释放锁,让其他线程获取锁 /// Pulse用于唤醒处于wait状态的线程 /// lock(obj) {...} 等效于 try { Monitor.Enter(obj, ref token); ...} finally { if (token) Monitor.Exit(obj); } /// </summary> private void MonitorTest() { var lck = new object(); var token = false; var t1 = Task.Run(() => { Output("1 start"); Monitor.TryEnter(lck, 500, ref token); if (token) { Output("1 Enter"); Thread.Sleep(3000); Monitor.Wait(lck); Output("1 wait end"); Monitor.Exit(lck); } else Output("1 Pass"); Output("1 end"); }); Thread.Sleep(100);//为了让t1先获取锁 Output("2 start"); lock (lck) { Output("Enter 2"); Thread.Sleep(3000); Monitor.Pulse(lck); Output("2 pulse end"); Thread.Sleep(3000); } Output("2 end"); Task.WaitAll(t1); } /// <summary> /// 为多个线程共享的变量提供原子操作 /// 为变更的加、减等操作提醒原子操作 /// </summary> private void InterLockedTest() { #if CODE1 //计数demo int cnt = 0; var tt1 = new Task(() => { for (int i = 0; i < 10000000; i++) //lock(this) { Interlocked.Increment(ref cnt); //cnt += 1; } }); var tt2 = new Task(() => { for (int i = 0; i < 10000000; i++) //lock(this) { Interlocked.Increment(ref cnt); //cnt += 1; } }); var ms = GetRunTime(() => { tt1.Start(); tt2.Start(); Task.WaitAll(tt1, tt2); }); Console.WriteLine(ms + " " + cnt); #else //用interlock保证只运行一次 int flag = 0; var tasksWithoutInterLocked = Enumerable.Range(0, 1000000).Select(_i => new Task(() => { if (flag != 0) return; Thread.Sleep(1);//模拟时间差 flag = 1; Console.WriteLine("maybe one"); })).ToArray(); foreach (var t in tasksWithoutInterLocked) t.Start(); Task.WaitAll(tasksWithoutInterLocked); Console.WriteLine("无InterLocked任务运行结束"); flag = 0; var tasksWithInterLocked = Enumerable.Range(0, 1000000).Select(_i => new Task(() => { if (0 == Interlocked.Exchange(ref flag, 1)) Console.WriteLine("only one"); })).ToArray(); foreach (var t in tasksWithInterLocked) t.Start(); Task.WaitAll(tasksWithInterLocked); Console.WriteLine("InterLocked任务运行结束"); #endif } /// <summary> /// 用于在两个线程之间进行信号发送, 保证不同线程间的执行顺序 /// 构造函数的 initialState 可以理解为门的状态,true表示门是开着的,false表示门的关闭的 /// 调用waitone的时候如果门是打开状态就直接进门然后自动关门, 如果门是关闭状态则等门开后进入 /// 调用Set表示开门, 然后第一个调用waitone的线程进入 /// 调用Reset表示关门 /// </summary> private void AutoResetEventTest() { var are = new AutoResetEvent(true); int loopTimes = 100; var t1 = Task.Run(() => { for (int i = 0; i < loopTimes; i++) { are?.WaitOne(); Output("1: " + i); Thread.Sleep(1); are?.Set(); } }); for (int i = 0; i < loopTimes; i++) { are?.WaitOne(); Output("----2: " + i); Thread.Sleep(1); are?.Set(); } Task.WaitAll(t1); } /// <summary> /// ManualResetEvent 基本与 AutoResetEvent 一致 /// 区别在于 AutoResetEvent 在WaitOne 后自动调用 Reset, ManualResetEvent 需要手动调用Reset对WaitOne进行阻塞 /// </summary> private void ManualResetEventTest() { } private void MethodImplAttributeTest() { var tasks = Enumerable.Range(0, 5).Select(_i => new Task(FuncWithMethidImpl)).ToArray(); foreach (var t in tasks) t.Start(); Task.WaitAll(tasks); } /// <summary> /// 整个方法上锁 /// </summary> [MethodImpl(MethodImplOptions.Synchronized)] private void FuncWithMethidImpl() { Output(""); Thread.Sleep(1000); } /// <summary> /// 读写锁 /// 使用ReaderWriterLock进行资源访问时,如果在某一时刻资源并没有获取写的独占权,那么可以获得多个读的访问权,单个写入的独占权,如果某一时 刻已经获取了写入的独占权,那么其它读取的访问权必须进行等待 /// AcquireReaderLock / ReleaseReaderLock 用于申请/释放读锁 /// AcquireWriterLock / ReleaseWriterLock 用于申请/释放写锁 /// </summary> private void ReaderWriterLockTest() { var lck = new ReaderWriterLock(); var funcRead = new Action(() => { lck.AcquireReaderLock(int.MaxValue); Output("read lock get"); Thread.Sleep(2000); Output("read lock release"); lck.ReleaseReaderLock(); }); var funcWrite = new Action(() => { Thread.Sleep(5);//为了让读锁先获取 lck.AcquireWriterLock(int.MaxValue); Output("write lock get"); Thread.Sleep(2000); Output("write lock release"); lck.ReleaseWriterLock(); }); var tr1 = new Task(funcRead); var tr2 = new Task(funcRead); var tr3 = new Task(funcRead); var tw1 = new Task(funcWrite); var tw2 = new Task(funcWrite); //先申请两个读锁再申请两个写锁再申请一个读锁 tr1.Start(); tr2.Start(); tw1.Start(); tw2.Start(); Thread.Sleep(100); tr3.Start(); Task.WaitAll(tr1, tr2, tr3, tw1, tw2); } /// <summary> /// 互斥锁,可用于进程间同步 /// 构造函数的 name 在操作系统中唯一 /// WaitOne加锁 /// ReleaseMutex解锁 /// WaitOne的执行次数和ReleaseMutex一定要一致 /// </summary> private void MutexTest() { using (var mutex = new Mutex(true, "whosyourdaddy", out bool isNew)) { if (isNew) Console.WriteLine("启动成功, 任意键退出"); else { Console.WriteLine("启动失败, 等待其他程序退出"); mutex.WaitOne(); Console.WriteLine("启动成功, 任意键退出"); } Console.ReadKey(); mutex.ReleaseMutex(); } } /// <summary> /// 信号量, 用来控制同时访问某个特定资源的操作数量,可用于进程间同步 /// WaitOne、Release /// </summary> private void SemaphoreTest() { using (Semaphore sem = new Semaphore(3, 3, "greedisgood")) { Console.WriteLine("start"); sem.WaitOne(); Console.WriteLine("enter"); Console.ReadKey(); sem.Release(); Console.WriteLine("exit"); } } private void Output(string msg) { Console.WriteLine(DateTime.Now.ToString("mm:ss.fff") + ": " + msg); } private long GetRunTime(Action action) { var watch = Stopwatch.StartNew(); action(); watch.Stop(); return watch.ElapsedMilliseconds; } } }
标签:may 使用 dad attr out 特定 token 进程间 释放
原文地址:https://www.cnblogs.com/onestow/p/12026509.html