首页 > 解决方案 > 在 C# 的多线程编程中读取局部变量是否安全?

问题描述

在 Java 中,除非添加final关键字,否则我们不能在线程之间共享局部变量。但在 C# 中,允许这样写:

void DoSomeJob() {

    bool isDone = false;

    new Thread( ()=> {
        // Do some background job

        isDone = true;
    }).Start();

    while (isDone == false) {
        // Do some foreground job
    }
}

实际上,这在我的简单测试中有效。

- 如您所见,没有 Thread.Sleep() 调用或任何类似的导致重新加载的东西。

- 在调试和发布模式下运行。

如果我必须像这样在线程之间共享一个变量(没有任何锁),我会将其定义为带有volatile关键字的静态变量,以防止陷入无限循环。所以我想知道像上面这样简单地读取一个局部变量是否总是有效的。

顺便说一句,这只是一个出于好奇的问题,而不是关于编写更好的多线程代码。

标签: c#multithreading

解决方案


在进行多线程处理时,您应该始终牢记一件事:只要一段代码不是原子的,它就可能被另一个线程中断。

分配一个 bool 值是原子的,但与它之前的计算一起它不是。

以您的代码为例,当新线程中的执行完成但 isDone bool 指标值尚未更新时,主线程可能只是检查 isDone 并发现它为 false。然而事实上,新线程中的执行实际上已经完成,因此主线程由于提前读取 isDone 指标 bool 值而做错了事。

如果主线程循环中的代码工作正常,无论其 isDone 与否,您的代码都会很好。


推荐阅读