C中的原子交换

时间:2014-01-18 03:58:19

标签: c macos atomic c11

我想我在这里遗漏了一些明显的东西。我有这样的代码:

int *a = <some_address>;
int *b = <another_address>;
[...]
int *tmp = a;
a = b; b = tmp;

我想原子地这样做。我一直在研究__c11_atomic_exchange和OSX OSAtomic方法,但似乎没有任何东西可以原子地执行直接交换。他们都可以原子地将2个变量的 1 写入一个值,但不能同时写两个。

有什么想法吗?

1 个答案:

答案 0 :(得分:5)

这取决于您的架构,有效和高效的可能性。在任何情况下,您都需要将要交换的两个指针在内存中相邻,最简单的就是像

那样。
typedef struct pair { void *a[2]; } pair;

然后你可以,如果你有一个完整的C11编译器使用_Atomic(pair)作为原子类型来交换这样的pair的内容:首先加载临时的实际对,构造一个新的如果交换了两个值,则执行比较交换以存储新值并在必要时进行迭代:

inline
void pair_swap(_Atomic(pair) *myPair) {
  pair actual = { 0 };
  pair future = { 0 };

  while (!atomic_compare_exchange_weak(myPair, &actual, future)) {
      future.a[0] = actual.a[1];
      future.a[1] = actual.a[0];
  }
}

根据您的体系结构,这可能是通过无锁原语操作实现的。现代64位架构通常具有128位原子,这可能导致只有128位汇编指令。

但这很大程度上取决于平台上原子实现的质量。 P99将为您提供一个实现,它实现原子操作的“功能”部分,并在检测到时支持128位交换;在我的机器上(64位Intel linux),这有效地编译成lock cmpxchg16b指令。