可以安全地在线程之间共享整数吗?

Mik*_*ike 7 c pthreads thread-safety

在没有任何同步实用程序的情况下,多个线程在C程序中的pthread之间使用相同的整数内存位置是否存在问题?

为了简化问题,

  • 只有一个线程会写入整数
  • 多个线程将读取整数

这个伪C说明了我的想法

void thread_main(int *a) {
  //wait for something to finish
  //dereference 'a', make decision based on its value
}

int value = 0;

for (int i=0; i<10; i++)
  pthread_create(NULL,NULL,thread_main,&value);
}
// do something
value = 1;
Run Code Online (Sandbox Code Playgroud)

我认为它是安全的,因为一个整数占用一个处理器字,读/写一个字应该是最原子的操作,对吧?

Ben*_*igt 12

你的伪代码不安全.

虽然访问一个字大小的整数确实是原子的,这意味着你永远不会看到一个中间值,但是"在写入之前"或"在写入之后",这对于你概述的算法来说是不够的.

您依赖于写入的相对顺序a并进行其他一些唤醒线程的更改.这不是原子操作,在现代处理器上无法保证.

您需要某种内存栅栏来防止写入重新排序.否则,不能保证其他线程能够看到新值.

  • 在x86和任何具有合理内存排序要求的平台上,或者在非SMP机器上,所有线程轮流在单个cpu上运行,使变量"volatile"就足够了.另一种方法是通过外部函数编写变量,该函数获取指向变量及其新值的指针.这将阻止重新排序,并且在病态体系结构上,您可以向此函数的cpu特定实现添加内存fence/barrier操作. (2认同)
  • @jonnycrash:"获得锁定的竞争条件"?我在哪里谈到锁定?而且你仍然专注于原子性,即使我的回答清楚地解释了这里的问题是排序,而不是原子性.最后,由于伪代码没有提出volatile的建议,所以它是错误的(即使在x86上,请注意问题从未说明代码只能在x86上运行).最后,您的"修复"是特定于编译器的.C++标准不需要用于易失性访问的内存栅栏,而C++内存模型处理顺序一致性,它(尚未)涵盖并行执行. (2认同)