分配原子函数的返回值

时间:2014-02-05 19:01:21

标签: multithreading locking race-condition spinlock compare-and-swap

我正在尝试实现一个屏障函数,这样当一个线程调用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个线程访问了这个,这个函数会起作用吗?原子函数的返回值的赋值是原子的吗?或者是否会出现竞争条件?

1 个答案:

答案 0 :(得分: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) {}
}