如果我有一个多线程程序通过引用读取缓存类型的内存.我可以通过主线程更改此指针,而不会冒任何其他线程读取意外值的风险.
在我看来,如果更改是原子的,其他线程将读取旧值或更新值; 从不随机内存(或空指针),对吧?
我知道无论如何我应该使用同步方法,但我仍然很好奇.
指针变化是原子的吗?
更新:我的平台是64位Linux(2.6.29),虽然我也想要一个跨平台的答案:)
正如其他人所提到的,C语言中没有任何内容可以保证这一点,而且它取决于您的平台.
在大多数现代桌面平台上,对字大小的对齐位置的读/写将是原子的.但由于处理器和编译器对读写的重新排序,这确实无法解决您的问题.
例如,以下代码被破坏:
线程A:
DoWork(); workDone = 1;
线程B:
while(workDone != 0); ReceiveResultsOfWork();
虽然写入workDone
是原子的,但在许多系统上,处理器无法保证workDone
在完成通过写入之前,写入对其他处理器DoWork()
是可见的.workDone
在调用之前,编译器也可以自由地重写命令DoWork()
.在这两种情况下,ReceiveResultsOfWork()
可能会开始处理不完整的数据.
根据您的平台,您可能需要插入内存挡板等,以确保正确的订购.为了做到这一点,这可能非常棘手.
或者只是使用锁.更简单,更容易验证是正确的,并且在大多数情况下足够高性能.
C语言没有说明任何操作是否是原子操作.我曾经研究过8位总线和16位指针的微控制器; 这些系统上的任何指针操作都可能是非原子的.我想我记得英特尔386s(其中一些有16位总线)引起了类似的担忧.同样,我可以想象具有64位CPU但32位数据总线的系统,这可能会引起与非原子指针操作类似的担忧.(我没有检查是否确实存在任何此类系统.)
编辑:迈克尔的回答非常值得一读.总线大小与指针大小不是关于原子性的唯一考虑因素; 这只是我想到的第一个反例.
你没有提到一个平台.所以我认为会有一个更准确的问题
指针变化是否保证是原子的?
区别是必要的,因为不同的C/C++实现可能会在此行为中有所不同.特定平台可以保证原子分配并且仍然在标准范围内.
至于这是否在C/C++中得到全面保证,答案是否定的.C标准没有这样的保证.保证指针赋值的唯一方法是使用特定于平台的机制来保证赋值的原子性.例如,Win32中的Interlocked方法将提供此保证.
你在做哪个平台?