为什么 volatile 会产生未定义的行为
Why does the volatile make an undefined behavior
按照我的理解,volatile
-qualified value是指无论什么时候访问,都必须去地址取最新的值。
现在我正在阅读 Effective Modern C++ 这本书,但我不明白 volatile
为什么在这里制作 UB:
volatile int vi(0); // initialize vi to 0
vi = 10; // set vi to 10
std::cout << vi; // read vi's value
++vi; // increment vi to 11
vi--; // decrement vi to 10
During execution of this code, if other threads are reading the value
of vi, they may see anything (e.g, -12, 68, 4090727—anything!). Such code would have undefined behavior, because these statements modify vi, so if other threads are reading vi at the same time, there are simultaneous readers and writers of memory that’s neither std::atomic nor protected by a mutex, and that’s the definition of a data race.
在我看来,如果其他线程可能看到0、10或11,我可以理解但是为什么书上说"they may see anything"?
本节讨论的是 volatile
对多线程编程是安全的常见误解。如果不同的线程同时读取和写入 vi
,那么就会出现 数据竞争 ,因为没有适当的同步或原子性保证。数据竞争在 C++ 中是未定义的行为,因此 "anything" 确实意味着什么。
如果改为使用正确的原子操作,那么可以保证对 vi
的所有修改都不会被其他线程中断,因此您不会出现数据竞争,您的程序也会很安全。或者,可以使用互斥锁或类似的方式引入同步。
请参阅 this site 中的参考资料,详细了解为什么 volatile
对这种事情不安全。
某些硬件实现可能有两个处理器共享异步内存,这似乎是合理的。如果一个处理器恰好在另一个处理器试图读取它时写入一个值,则这些位可能会在读取操作的中间逐字改变,这样第二个处理器就会看到新旧值的任意混合。更糟糕的是,某些处理器可能会发生故障
如果值由于称为亚稳态的硬件问题而在读取时精确更改,则情况会很糟糕。
是否任何可以 运行 C++ 的机器都会有这样的亚稳定性问题[硬件设计者在过去 35 年中已经学到了很多关于如何避免它们],标准的作者没有想要强加合理的实现难以满足的要求。
按照我的理解,volatile
-qualified value是指无论什么时候访问,都必须去地址取最新的值。
现在我正在阅读 Effective Modern C++ 这本书,但我不明白 volatile
为什么在这里制作 UB:
volatile int vi(0); // initialize vi to 0
vi = 10; // set vi to 10
std::cout << vi; // read vi's value
++vi; // increment vi to 11
vi--; // decrement vi to 10
During execution of this code, if other threads are reading the value of vi, they may see anything (e.g, -12, 68, 4090727—anything!). Such code would have undefined behavior, because these statements modify vi, so if other threads are reading vi at the same time, there are simultaneous readers and writers of memory that’s neither std::atomic nor protected by a mutex, and that’s the definition of a data race.
在我看来,如果其他线程可能看到0、10或11,我可以理解但是为什么书上说"they may see anything"?
本节讨论的是 volatile
对多线程编程是安全的常见误解。如果不同的线程同时读取和写入 vi
,那么就会出现 数据竞争 ,因为没有适当的同步或原子性保证。数据竞争在 C++ 中是未定义的行为,因此 "anything" 确实意味着什么。
如果改为使用正确的原子操作,那么可以保证对 vi
的所有修改都不会被其他线程中断,因此您不会出现数据竞争,您的程序也会很安全。或者,可以使用互斥锁或类似的方式引入同步。
请参阅 this site 中的参考资料,详细了解为什么 volatile
对这种事情不安全。
某些硬件实现可能有两个处理器共享异步内存,这似乎是合理的。如果一个处理器恰好在另一个处理器试图读取它时写入一个值,则这些位可能会在读取操作的中间逐字改变,这样第二个处理器就会看到新旧值的任意混合。更糟糕的是,某些处理器可能会发生故障 如果值由于称为亚稳态的硬件问题而在读取时精确更改,则情况会很糟糕。
是否任何可以 运行 C++ 的机器都会有这样的亚稳定性问题[硬件设计者在过去 35 年中已经学到了很多关于如何避免它们],标准的作者没有想要强加合理的实现难以满足的要求。