线程同步(笔记)
两种情况:用户模式和内核模式
一 用户模式
相当于运行自己写的程序,在里面设置线程同步
有volatile和interlocked两者方式
1 volatile
static bool _stop; public static void Run() {//主线程 Task.Run(() => {//任务线程 int number = 1; while (!Volatile.Read(ref _stop)) //读取_stop { number++; } Console.WriteLine($"increase stopped,value = {number}"); }); Thread.Sleep(1000); _stop = true; //更新_stop }
2 interlocked
private static void DoIncrease(int incrementPerThread) { int number1 = 0; int number2 = 0; Console.WriteLine($"use two threads to increase zero. each thread increase {incrementPerThread}."); IList<Task> increaseTasks = new List<Task>(); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number1."); for (int i = 0; i < incrementPerThread; i++) { Interlocked.Increment(ref number1); } })); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number1."); for (int i = 0; i < incrementPerThread; i++) { Interlocked.Increment(ref number1); } })); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number2."); for (int i = 0; i < incrementPerThread; i++) { number2++; } })); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} increasing number2."); for (int i = 0; i < incrementPerThread; i++) { number2++; } })); Task.WaitAll(increaseTasks.ToArray()); Console.WriteLine($"use interlocked: number1 result = {number1}"); Console.WriteLine($"normal increase: number2 result = {number2}"); }
二 内核模式
有事件、信号量和互斥量这三种方式
1 事件 AutoResetEvent
private static void DoIncrease(int incrementPerThread) { int number = 0; Console.WriteLine($"use two threads to increase zero. each thread increase {incrementPerThread}."); AutoResetEvent are = new AutoResetEvent(true);//初始化一个终止状态的线程同步事件 IList<Task> increaseTasks = new List<Task>(); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number."); for (int i = 0; i < incrementPerThread; i++) { are.WaitOne();// 阻塞线程,直到被同步事件唤醒 number++; are.Set();// 将事件设为终止状态,唤醒其他线程 } })); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number."); for (int i = 0; i < incrementPerThread; i++) { are.WaitOne(); number++; are.Set(); } })); Task.WaitAll(increaseTasks.ToArray()); are.Dispose(); Console.WriteLine($"use AutoResetEvent: result = {number}"); }
2 信号量 Semaphore
private static void DoIncrease(int incrementPerThread) { int number = 0; Console.WriteLine($"use two threads to increase zero. each thread increase {incrementPerThread}."); Semaphore semaphore = new Semaphore(1,1); //初始化信号量,这里初始值要设置为1,否则同步会有问题 IList<Task> increaseTasks = new List<Task>(); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number."); for (int i = 0; i < incrementPerThread; i++) { semaphore.WaitOne(); number++; semaphore.Release(1);// 退出信号量 } })); increaseTasks.Add(Task.Run(() => { Console.WriteLine($"thread #{Thread.CurrentThread.ManagedThreadId} is increasing the number."); for (int i = 0; i < incrementPerThread; i++) { semaphore.WaitOne(); number++; semaphore.Release(1); } })); Task.WaitAll(increaseTasks.ToArray()); semaphore.Dispose(); Console.WriteLine($"use Semaphore: result = {number}"); }
3 互斥量 Mutex
bool createNew; using (new Mutex(true, Assembly.GetExecutingAssembly().FullName, out createNew)) { if (!createNew) {//系统已经存在同名的互斥体,说明已有程序实例在运行 //这里做一些提示 Environment.Exit(0);//退出 } else { //启动实例的代码 } }
三 混合模式
1 Lock
2 ReaderWriterLockSlim
private static readonly ReaderWriterLockSlim _rwlock = new ReaderWriterLockSlim(); public static void DoWork() { _rwlock.EnterWriteLock(); //DoWork _rwlock.ExitWriteLock(); }