(精华)2020年12月23日 .NET Core 多线程底层详解(线程本地存储)

tech2024-12-09  5

一般来说线程都是有自己上下文,变量是不共享的,这就需要线程本地存储

public static class TlsSample { [ThreadStatic] public static int a; [ThreadStatic] public static int b; public static void Thread1() { a = 1; b = 2; Console.WriteLine($"a={a} [From Thread1]"); Console.WriteLine($"b={b} [From Thread1]"); } public static void Thread2() { a = 10; b = 20; Console.WriteLine($"a={a} [From Thread2]"); Console.WriteLine($"b={b} [From Thread2]"); } public static void Run() { var thread1 = new Thread(Thread1); var thread2 = new Thread(Thread2); thread1.Start(); thread2.Start(); } } public class ThreadLocalSample { public readonly ThreadLocal<int> a = new ThreadLocal<int>(); public readonly ThreadLocal<int> b = new ThreadLocal<int>(); public void Thread1() { a.Value = 1; b.Value = 2; Console.WriteLine($"a={a} [From Thread1]"); Console.WriteLine($"b={b} [From Thread1]"); } public void Thread2() { a.Value = 10; b.Value = 20; Console.WriteLine($"a={a} [From Thread2]"); Console.WriteLine($"b={b} [From Thread2]"); } public void Run() { var thread1 = new Thread(Thread1); var thread2 = new Thread(Thread2); thread1.Start(); thread2.Start(); } }

异步本地变量AsyncLocal(执行上下文)

public static class Sample07 { private static readonly ThreadLocal<int> ThreadLocal = new ThreadLocal<int>(); private static readonly AsyncLocal<int> AsyncLocal = new AsyncLocal<int>(); public static async Task Run() { ThreadLocal.Value = 10; AsyncLocal.Value = 10; Console.WriteLine($"Tid={Thread.CurrentThread.ManagedThreadId};" + $"ThreadLocal={ThreadLocal.Value};" + $"AsyncLocal={AsyncLocal.Value}"); await Task.Delay(1000); Console.WriteLine($"Tid={Thread.CurrentThread.ManagedThreadId};" + $"ThreadLocal={ThreadLocal.Value};" + $"AsyncLocal={AsyncLocal.Value}"); } }

不变性值类型子任务异步变量修改不会变,引用会

public static class Sample08 { private static readonly AsyncLocal<int> AsyncLocal = new AsyncLocal<int>(); public static async Task ParentTask() { AsyncLocal.Value = 111; Console.WriteLine($"ParentTask Begin:AsyncLocal={AsyncLocal.Value}"); await ChildTask(); Console.WriteLine($"ParentTask End:AsyncLocal={AsyncLocal.Value}"); } public static async Task ChildTask() { Console.WriteLine($"ChildTask Begin:AsyncLocal={AsyncLocal.Value}"); AsyncLocal.Value = 222; await Task.Delay(1000); Console.WriteLine($"ChildTask End:AsyncLocal={AsyncLocal.Value}"); } }

禁止捕捉执行上下文,则无法传递到其他线程

public static class Sample11 { private static readonly AsyncLocal<int> AsyncLocal = new AsyncLocal<int>(); public static async Task ParentTask() { AsyncLocal.Value = 111; Console.WriteLine($"ParentTask Begin:AsyncLocal={AsyncLocal.Value}"); // 禁止捕捉执行上下文 var control = ExecutionContext.SuppressFlow(); Task.Delay(100).ContinueWith(task => { Console.WriteLine($"SuppressFlow:AsyncLocal={AsyncLocal.Value}"); }); // 恢复捕捉上下文 control.Undo(); // 捕捉到的执行上下文为null await Task.Delay(100); Console.WriteLine($"Undo:AsyncLocal={AsyncLocal.Value}"); } }
最新回复(0)