Lor*_*one 0 c c++ mutex volatile thread-safety
我是唯一这么认为的人吗?[真正的问题在一秒钟内.]
除了对它的巨大混淆,以及它与互斥或其他锁定机制的混合,当我处理线程安全情况时,我总是不得不放弃任何使用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
Run Code Online (Sandbox Code Playgroud)
现在,编译器可能希望优化两个线程A的读取,从而将一些结果保存在寄存器中.你说我应该宣布那些变量为volatile
.我说我不想标记所有内容volatile
,因为它volatile
是透明的,我必须复制50%的代码才能支持volatile
类型.您(他)说锁定互斥锁(至少是POSIX互斥锁)是编译器识别并正确管理的东西,要么是对库的调用(编译器无法访问),这可能会改变世界,所以编译器这样的电话会议后不会做任何事情.我说这是依赖于实现的,非常低级别的东西(我不想浏览开发文档以进行日常编程).更糟糕的是,如果由于某种原因,出于某种原因,"外部库"由于任何合法的原因而变得可供编译器访问(可能是作者在必须包含在头文件中的模板中转换函数......无论如何),它会突然改变.
所以,在我看来,volatile
完全没用(和误导),除非是一些非常低级别的东西(设备读取可能,但我不能胜任这样的领域).
更好的方法是明确告诉编译器它必须放弃任何关于任何变量的假设,并且每次后续读取必须是从内存中读取的真实内容.但是我无法想象比调用虚拟外部函数更好的事情,这会产生我之前概述的相同问题.有一种优雅的方式吗?
我使用低级别的东西,这是一个有用的例子.
volatile uint32_t *foo = <<<a register on a pci device>>>
Run Code Online (Sandbox Code Playgroud)
有可能在foo
多次阅读时,我会得到不同的结果.这是因为外部源(pci设备)正在修改它.例如,foo
可能意味着当前时间.
当我写信时foo
,它可能与可能出现的内容几乎没有关系.例如,我可能有一个存储一些警报位的寄存器.我会写那些位来清除它们.因此,如果寄存器foo
具有值0x72
,我可能会写入0x2
寄存器,这可能导致该寄存器中的结果值0x70
.
volatile
允许我使用这些语义.
归档时间: |
|
查看次数: |
147 次 |
最近记录: |