在简单的情况下同时写入和读取布尔值的危险

Sha*_*dor 3 c++ multithreading nonatomic

我已经阅读了一些类似的问题,但那里描述的情况有点复杂.

我在堆中有一个bool b初始化false和两个线程.我确实理解操作boolsnot atomic,但请直到最后阅读问题.

第一个线程只能设置b = true一次,不会对它做任何其他事情.第二个线程检查b一个循环,如果它true做了一些动作.

我是否需要使用某些同步机制(如互斥锁)来保护b?如果我不这样做会怎么样?随着ints我能明显得到任意值,当我读到,并在同一时间写.但是,bools只有true而且false我不介意一次得到false而不是true.这是一种潜力SIGSEGV吗?

Ste*_*sop 7

数据争用导致未定义的行为.就标准而言,允许符合条件的实现是段错误的.

在实践中,主要的危险是如果没有同步,编译器将在读取器循环中观察足够的代码以判断b"永不改变",并优化除了第一次读取值之外的所有代码.它可以这样做,因为如果它观察到循环中没有同步,那么它知道对值的任何写入都是数据争用.允许优化器假设您的程序不会引发未定义的行为,因此允许假设没有来自其他线程的写入.

标记bvolatile将在实践中阻止此特定优化,但即使volatile对象数据竞争也是未定义的行为.调用优化程序"无法看到"的代码也会阻止实际优化,因为它不知道代码是否会修改b.当然,对于链接时/整个程序优化,优化器看不到的内容少于仅编译时优化.

无论如何,防止在软件中进行优化并不能防止在具有非连贯缓存的系统上硬件中发生的同等事情(至少,我声称:其他人认为这是不正确的,并且volatile访问是必需的通过缓存读/写.有些实现的行为就是这样.如果你问的是标准是什么意思,那么硬件是否无限期地向你显示陈旧的缓存并不重要,因为行为仍然是未定义的,所以无论这个特定的优化是什么,实现都会破坏你的代码打破它.

  • @Jan:**没有**.`volatile`与Java中的含义不同. (3认同)
  • 请不要骂我这个问题,因为仅仅提到一些人的世界"挥发性"似乎会引起骚动.`volatile`会对抗你引用的优化有什么影响吗? (2认同)
  • 是的,它会产生影响,但这将是一个使用错误工具的不必要的低效解决方案.如果变量标记为"volatile",那么对该变量的所有读/写都是可观察的,这意味着它们必须按照您指定的方式发生(它们不能重新排序或优化掉).`volatile`的问题在于它无法保证这些访问如何针对*other*(非易失性)代码进行重新排序,并且`volatile`适用于*all*访问变量*ever*.通常,您只想同步*某些*访问 (2认同)