C#中值类型局部变量为何被多线程共享?
为什么三个线程能共享栈上的int变量?
你对值类型存储和线程栈的认知是对的,但这里的count变量因为闭包捕获的机制,实际存储位置已经发生了变化:
- 当你在匿名委托里引用外部方法的
count变量时,C#编译器会自动生成一个隐藏的类,把count作为这个类的字段(虽然int是值类型,但这个类是引用类型,实例存储在堆上)。 - 你创建的三个线程的委托,都会持有这个隐藏类实例的引用,所以三个线程操作的是同一个堆上的
count字段,自然会共享变量值,最终能累加到300(注:这段代码存在线程安全问题,极端情况下可能出现计数小于300的情况,因为++count不是原子操作)。
对比一下,如果把变量放到委托内部,每个线程就会拥有独立的局部变量:
Thread a = new Thread(delegate () { int threadCount = 0; // 每个线程自己的局部变量,存储在当前线程栈上 for (int i = 0; i < 100; i++) { Console.WriteLine($"Thread ID : {Thread.CurrentThread.ManagedThreadId}, Count : {++threadCount}"); } });
你的测试代码:
public void Test() { int count = 0; Thread a = new Thread(delegate () { for (int i = 0; i < 100; i++) { Console.WriteLine($"Thread ID : {Thread.CurrentThread.ManagedThreadId}, Count : {++count}"); } }); a.Start(); Thread b = new Thread(delegate () { for (int i = 0; i < 100; i++) { Console.WriteLine($"Thread ID : {Thread.CurrentThread.ManagedThreadId}, Count : {++count}"); } }); b.Start(); Thread c = new Thread(delegate () { for (int i = 0; i < 100; i++) { Console.WriteLine($"Thread ID : {Thread.CurrentThread.ManagedThreadId}, Count : {++count}"); } }); c.Start(); }
内容的提问来源于stack exchange,提问作者taebong
相关产品推荐
相关产品推荐

