如果我有这样的东西...
volatile long something_global = 0;
long some_public_func()
{
return something_global++;
}当使用多个线程访问时,期望这段代码不会中断(竞争条件)是否合理?如果它不是标准的,那么它仍然可以作为现代编译器的合理假设吗?
注意:我使用它的唯一目的是原子递增和递减--没有更花哨的东西。
发布于 2010-06-26 09:52:16
无易失性并不意味着已同步。它只是意味着每次访问都将返回最新的值(而不是线程中本地缓存的副本)。
后增量不是原子操作,它是内存访问,然后是内存写入。交错两个可能意味着该值实际上只递增一次。
发布于 2010-06-26 10:03:42
不,您必须使用与平台相关的原子访问。有几个库对这些进行了抽象-- GLib提供了可移植的原子操作,如果需要,这些操作可以回退到互斥锁,我相信Boost也提供了可移植的原子。
作为我的recently learned,对于真正的原子访问,你需要一个volatile没有提供的完整的内存屏障。所有易失性保证是存储器将在每次访问时被重新读取,并且对volatile存储器的访问将不会被重新排序。优化器可以在易失性读/写之前或之后对某些非易失性访问进行重新排序--可能是在递增过程中!--因此必须使用实际的原子操作。
发布于 2010-06-26 10:00:59
在现代快速多核处理器上,由于缓存和写缓冲区,原子指令的开销很大。
因此,编译器不会仅仅因为添加了volatile关键字就发出原子指令。您需要求助于内联汇编或编译器特定的扩展(例如gcc atomic builtins)。
我推荐使用库。最简单的方法是,当您想要更新变量时,只使用一个锁。如果信号量适合于您正在做的事情,那么它们可能会更快。看起来GLib提供了一个相当高效的实现。
https://stackoverflow.com/questions/3122382
复制相似问题