线程之间的共享变量是否总是需要保护?

时间:2014-06-17 17:19:49

标签: multithreading thread-safety race-condition

假设我有两个线程正在读取并修改bool / int“state”。处理器保证读取和写入是原子的。

Thread 1:

if (state == ENABLED)
{
    Process_Data()
}

Thread 2:

state = DISABLED

在这种情况下,是的,线程1可以读取状态并进入它的“if”到Process_Data,然后Thread2可以改变状态。但是那时仍然没有继续处理Process_Data。是的,如果我们查看引擎盖,我们的状态是DISABLED并且我们进入Process_Data函数是不一致的。但是在Thread1执行下一次执行后,它将获得state = DISABLED而不是Process_Data。

我的问题是,我仍然需要锁定这两个线程以使Thread1的check-state-and-process原子和Thread2的写入原子(wrt to Thread 1)?

2 个答案:

答案 0 :(得分:0)

你已经解决了原子性问题。但是,在现代处理器中,您不仅要担心原子性,还要担心内存可见性。

例如,线程1在一个处理器上执行,并从state读取ENABLED - 来自其处理器的缓存。

同时,线程2在不同的处理器上执行,并在其处理器的缓存上将DISABLED写入state

没有进一步的代码 - 在某些语言中,例如,声明state volatile - DISABLED值可能无法长时间刷新到主内存。如果线程2最终将值更改回ENABLED,它可能永远不会刷新到主存储器。

同时,即使将DISABLED值刷新到主存储器,线程1也可能永远不会将其拾取,而是继续无限期地使用其缓存的ENABLED值。

通常,如果要在线程之间共享值,最好使用适当的机制来显式使用您正在使用的编程语言和环境。

答案 1 :(得分:0)

通常无法回答您的问题。如果您使用的语言,编译器,线程库和/或平台的规范说您需要保护,那么您可以这样做。如果它说你没有,那么你就不会。我相信每个线程库或多线程实现都指定了合理使用和共享数据的规则。如果你的不是,它是一块无法可靠使用的垃圾,你应该得到一个更好的垃圾。

不要犯错误思考,"这是安全的,因为我无法想出任何可能出错的方式。"或者"我测试了这个,我无法让它失败,所以它是安全的。"当您更改编译器选项,升级CPU或在不同平台上运行程序时,这种思维会产生易碎的代码,这些代码往往会失败。请遵循您使用的工具的规格。