3

如果存在指针“A”和“B”,则要求在对“B”的任何写入可见之前,应使对“A”的任何写入可见。如果不允许我使用锁并且不允许我将这些变量声明为“volatile”,那么以下代码是否可以保证满足上述要求?

volatile temp;

*A = value1;
temp = *A;

if (temp == value1) {
    *B = value2
}
4

4 回答 4

3

您将需要使用内存屏障或栅栏:请参阅http://en.wikipedia.org/wiki/Memory_barrier

在 Linux 内核中,您可以使用rmb()orwmb()调用。

pthreads你可以使用pthread_barrier_wait()的下面,虽然这似乎不在我的 pthreads 联机帮助页中。

在 MSVC 上,查看强制执行 C 语句的顺序?- 它也有一些很好的一般信息。

如果你找到一个“原子”库,那通常会包含屏障函数。

于 2014-03-01T12:52:49.490 回答
2

答案很简单。你不能。可能会发生重新排序,因为:

  • 编译器将决定重新排序(允许这样做,尽管这取决于编译器标志等);
  • 处理器将决定重新订购。如果处理器足够复杂,它肯定会这样做。

要强制内存排序,您需要同步。不幸的是,这里有很多方法。每种方法都有其优点和缺点。根据您的情况,您需要选择一些。

于 2014-03-01T13:17:41.087 回答
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 的存储指令之后,这仍然不能保证其他线程按该顺序“看到”修改。这将取决于缓存同步并且基本上是不可预测的。您将需要内存屏障或锁定机制以使其可靠地工作。

于 2014-03-01T15:19:00.627 回答
0

不,不会的。而且你也没有办法利用易失性和简单的 C 构造来实现它。只要您的程序正常运行,编译器就可以自由地重新排序您的代码(其他任何人都该死!)

所以问题是:您还可以调用哪些其他选项?例如,如果唯一的要求是另一个任务永远不会看到无序的更新,那么您可以通过在设置 A 和 B 之间进行任何系统调用来有效地保证这一点。即使是对远程内存位置中的库函数的调用也可能会执行工作。您真正需要做的就是超过可能的最长管道。但这可能需要一段时间...

这让我想到了一个问题:你将如何测试这个?它的时间紧迫性如何?

可能需要更多信息才能真正回答这个问题。

于 2014-03-01T14:20:33.087 回答