线程中的内存如何分配?为何C#示例代码线程输出两个t2而非t1和t2
问题根因分析
核心问题是C# Lambda表达式的闭包变量捕获机制和线程调度的异步性共同作用导致的:
- 你代码中两个Lambda表达式捕获的都是同一个局部变量
text,而非Lambda定义时该变量的快照值。也就是说Lambda内部访问的是变量本身的内存地址,不是定义时拷贝的临时值。 - 调用
t1.Start()后线程不会立刻执行,操作系统需要时间调度线程执行。主线程在调用t1的启动方法后会立刻继续向下执行,先完成text = "t2"的赋值操作,等到t1线程真正被调度运行、执行Console.WriteLine(text)时,读取到的text已经是修改后的值t2,最终两个线程输出的都是t2。
修复方案
要解决这个问题,只需要在定义每个Lambda的作用域内新增一个临时局部变量,拷贝当前text的值,让Lambda捕获这个作用域独立的临时变量即可:
class Program { static void Main() { string text = "t1"; // 定义t1专属的临时变量,被Lambda捕获 string tempForT1 = text; Thread t1 = new Thread(() => Console.WriteLine(tempForT1)); t1.Start(); text = "t2"; // 定义t2专属的临时变量,被Lambda捕获 string tempForT2 = text; Thread t2 = new Thread(() => Console.WriteLine(tempForT2)); t2.Start(); } }
注意:修改后仅能保证两个输出的值分别为
t1和t2,输出顺序仍可能因为操作系统线程调度的不确定性发生变化,不会固定为先输出t1再输出t2。
内容的提问来源于stack exchange,提问作者Abdullah
相关产品推荐
相关产品推荐

