1

我正在尝试实现一个屏障函数,这样当一个线程调用waitBarrier()它时,它将等到所有其他n线程都调用了该函数,之后一切都会继续进行,即一种同步构造。

我有以下代码:

int i = 0; // Shared variable. Initialized as 0 at the beginning.

waitBarrier() {

  // CAS = Compare-and-swap, the first argument holds "old_val" the second the new
  i = CAS(i, i+1);

  // Spin until all n threads (number of all threads known prior) have been "here"
  while (i != n) {}

}

如果这被n线程访问,这个函数会起作用吗?原子函数返回值的赋值是原子的吗?或者可能会出现竞争条件?

4

1 回答 1

2

首先,您必须指定寄存器的地址,即您要比较和交换的值。这可以通过以下任一方式完成:

CAS(int* reg, int oldValue, int newValue)

或者

reg.CAS(int oldValue, int newValue)

假设您现在的线路是:

i = i.CAS(i, i+1)

想象一下两个线程waitBarrier()同时调用。假设原子函数的参数被非原子地评估,即两个线程实际上都会调用i.CAS(0,1)

无论谁首先执行原子调用,都会成功地将共享变量 i 设置为 1。由于 CAS 确实总是返回旧值,因此通过赋值i = OLD_VALUE_OF_i,您实际上是将共享变量重置为 0。不仅如此,而且想象一下您会省略该分配完全并且刚刚进行了 CAS 调用,无论谁执行 CAS 第二个线程都会将共享值的值(现在将为 1)与 i 的初始值(在评估时为 0 的参数)进行比较,这将失败因此共享变量只会增加一次!

考虑到这两个方面,您的代码必须如下所示:

int i = 0;

waitBarrier() {
  // Atomically increment the shared value i by 1
  do {
    int value = i;
  } while (CAS(i, value, value + 1));

  // Wait until all threads have passed the barrier
  while (i != n) {}
}
于 2014-02-08T16:08:10.997 回答