Hon*_*gli 46 c++ concurrency multithreading
假设我在类中有一个整数变量,并且该变量可能被其他线程同时修改.写入受互斥锁保护.我是否也需要保护读取?我听说有一些硬件架构,如果一个线程修改一个变量,另一个线程读取它,那么读取结果将是垃圾; 在这种情况下,我确实需要保护读取.我从未见过这样的架构.
这个问题假设单个事务只包含更新单个整数变量,因此我不担心可能也涉及事务的任何其他变量的状态.
pet*_*hen 34
原子读
如前所述,它依赖于平台.在x86上,该值必须在4字节边界上对齐.通常,对于大多数平台,读取必须在单个CPU指令中执行.
优化程序缓存
优化程序不知道您正在读取由其他线程修改的值.声明该值volatile有助于:优化器将为每次访问发出内存读/写,而不是试图将值缓存在寄存器中.
CPU缓存
尽管如此,您可能会读取过时的值,因为在现代体系结构中,您有多个具有单独缓存且未自动保持同步的内核.您需要一个读取内存屏障,通常是特定于平台的指令.
在Wintel上,线程同步功能会自动添加完整的内存屏障,或者您可以使用InterlockedXxxx函数.
MSDN:内存和同步问题,MemoryBarrier宏
[编辑]也请看drhirsch的评论.
Gun*_*iez 15
您询问有关读取变量的问题,然后讨论更新变量,这意味着读取 - 修改 - 写入操作.
假设你真的是指前者,那么如果它是原子操作,则读取是安全的.对于几乎所有的体系结构,这对整数来说都是正确的.
有一些(和罕见的)例外:
在这种情况下,我建议不要依赖任何编译器或体系结构.
每当你有一群读者和作家(而不仅仅是读者或只是作家)时,你最好将它们全部同步.想象一下,你的代码运行的是一个人的心脏,你真的不希望它读错了值,你肯定不希望你所在城市的电厂变得"沸腾",因为有人决定不使用那个互斥锁.从长远来看,让自己保持睡眠,同步他们.
如果你只有一个线程读取 - 你只使用那个互斥锁是好的,但是如果你计划多个读者和多个编写者,你需要一个复杂的代码来同步它.我还没有看到一个很好的读/写锁实现,它也是"公平的".
想象一下,您正在一个线程中读取变量,该线程在读取时被中断,并且该变量由写入线程更改.现在读取线程恢复后读取整数的值是多少?
除非读取变量是原子操作,在这种情况下只需要一条(汇编)指令,否则无法确保上述情况不会发生.(该变量可以写入内存,检索该值将需要多条指令)
一致意见是你应该单独封装/锁定所有写入,而读取可以与(仅)其他读取同时执行