如果存在指针“A”和“B”,则要求在对“B”的任何写入可见之前,应使任何对“A”的写入可见。如果我不被允许使用锁,并且如果我不允许将这些变量声明为“volatile”,那么以下代码是否会保证满足上述要求?
volatile temp;
*A = value1;
temp = *A;
if (temp == value1) {
*B = value2
}
答案 0 :(得分:3)
您需要使用内存屏障或围栏:请参阅http://en.wikipedia.org/wiki/Memory_barrier
在Linux内核中,您可以使用rmb()
或wmb()
来电。
在pthreads
下,您可以使用pthread_barrier_wait()
,但这似乎不在我的pthreads联机帮助页中。
在MSVC上,查看Force order of execution of C statements? - 这也有一些很好的一般信息。
如果找到'原子'库,通常会包含屏障函数。
答案 1 :(得分:2)
答案很简单。你不能。重新排序可能因为:
要强制进行内存排序,您需要同步。不幸的是,这里有很多方法。每种方法都有自己的优点和缺点。根据您的情况,您需要选择一些。
答案 2 :(得分:1)
我认为C编译器重新排序您的示例代码是完全合法的:
volatile temp;
old_b = *B;
*B = value2;
*A = value1;
temp = *A;
if (temp != value1) {
*B = old_b;
}
这样的事情可能会更好:
volatile temp;
temp = value1;
*A = temp;
temp = value2;
*B = temp;
但即使您知道B的存储指令出现在A的存储指令之后,这仍然不能保证其他线程“看到”该顺序的修改。这将取决于缓存同步,基本上是不可预测的。您需要内存屏障或锁定机制才能使其可靠运行。
答案 3 :(得分:0)
不,它不会。并且你无法用易失性和简单的C结构来实现它。只要您的程序正常工作(并且其他任何人都被诅咒!),编译器可以自由地重新排序您的代码。
所以问题是:你还可以考虑其他什么选择?例如,如果唯一的要求是另一个任务永远不会看到无序更新,则可以通过在设置A和B之间进行任何系统调用来有效地保证。即使在远程内存位置调用库函数也可能会工作。您真正需要做的就是超越尽可能长的管道。但这可能需要一段时间......
这让我想到了一个问题:你打算如何测试?它的时间关键性如何?
可能需要更多信息才能真正回答这个问题。