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

时间:2011-01-03 22:20:08

标签: c thread-safety pthreads

在没有任何同步实用程序的情况下,多个线程在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;

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

7 个答案:

答案 0 :(得分:12)

您的伪代码不安全。

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

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

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

答案 1 :(得分:1)

与显式启动线程的java不同,posix线程立即开始执行 因此,无法保证在主要功能中设置为1的值(假设您在伪代码中引用的值)将在线程尝试访问它之前或之后执行。
因此,虽然同时读取整数是安全的,但如果需要写入该值以供线程使用,则需要进行一些同步。
否则,无法保证他们将阅读的价值是什么(为了根据你注意的价值采取行动) 你不应该对多线程做出假设,例如在每个线程中有一些处理来访问值等 没有保证

答案 2 :(得分:0)

我不会指望它。编译器可能会发出代码,假定它知道CPU寄存器中任何给定时间的'value'值是什么,而无需从内存中重新加载它。

答案 3 :(得分:0)

答案 4 :(得分:-1)

嗯,我想它是安全的,但为什么不直接声明一个函数将值返回给其他线程,因为它们只能读取它?

因为简单的想法是将指针传递给单独的线程已经是一个安全性失败,在我看来。我告诉你的是:当你只需要值时,为什么要提供一个(可修改的,可公开访问的)整数地址?

答案 5 :(得分:-1)

假设你在休眠一秒钟时在线程函数中做的第一件事。因此,之后的价值肯定是1。

答案 6 :(得分:-1)

在任何时刻,您至少应声明共享变量volatile。但是,在所有情况下,您都应该更喜欢其他形式的线程IPC或同步;在这种情况下,看起来condition variable就是你真正需要的。