只有我这么想吗?[一秒钟的真正问题。]
除了关于它的巨大混乱,以及它与互斥锁或其他锁定机制的混合,当我处理线程安全情况时,我总是不得不放弃任何使用volatile
,因为它根本没有做任何有用的事情。
volatile
“禁止对读/写进行任何重新排序或缓存”,但这并没有多大用处,只要volatile
标记一个对象(并污染它,因为它不再是“正常”对象)。
考虑一下:
Thread A Thread B
reads vars
locks mutex (gets access)
locks mutex (waits)
writes some vars
releases mutex
reads vars again
releases mutex
现在,编译器可能想要优化两个线程 A 的读取,将一些结果保存在寄存器中。你说我应该将这些变量声明为volatile
. 我说我不想将所有内容都标记为volatile
,因为volatile
它是透明的,我必须复制 50% 的代码来支持volatile
类型。你(他) 说锁定互斥锁(至少是 POSIX 互斥锁)要么是编译器可以识别并正确管理的东西,要么是对可以改变世界的库(编译器无法访问)的调用,因此编译器不会假设在这样的电话之后的任何事情。我说这太依赖于实现,非常低级的东西(我不想浏览开发文档进行日常编程)。更糟糕的是,如果由于某种原因“外部库”,出于任何合法原因,编译器可以访问,它可能会突然改变(也许作者将函数转换为必须包含在头文件中的模板......无论如何) .
因此,在我看来,volatile
这是完全没用的(并且具有误导性),除非对于一些非常低级的东西(可能是设备读取,但我在这个领域不胜任)。
更好的是用其他方式明确告诉编译器它必须放弃关于任何变量的任何假设,并且每次后续读取都必须是从内存中真正读取。但我想不出有什么比调用一个虚拟外部函数更好的了,这会产生我之前概述的相同问题。有没有一种优雅的方式来做到这一点?