Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 读而不写共享变量是线程安全的吗?_C_Multithreading_Thread Safety_Pthreads - Fatal编程技术网

C 读而不写共享变量是线程安全的吗?

C 读而不写共享变量是线程安全的吗?,c,multithreading,thread-safety,pthreads,C,Multithreading,Thread Safety,Pthreads,使用Pthreads,假设在线程1和线程2之间有一个全局共享变量foo。在不使用互斥锁的情况下从线程1读取foo的值是否是线程安全的?请注意,当线程1读取foo时,线程2可能会更改其值(当然,它会事先锁定互斥锁) 情况是这样的: #include <pthread.h> ... int foo; pthread_mutex_t mutex; ... void *thread1(void *t) { while (foo<10) { // do stuff }

使用Pthreads,假设在线程1和线程2之间有一个全局共享变量
foo
。在不使用互斥锁的情况下从线程1读取
foo
的值是否是线程安全的?请注意,当线程1读取
foo
时,线程2可能会更改其值(当然,它会事先锁定互斥锁)

情况是这样的:

#include <pthread.h>
...
int foo;
pthread_mutex_t mutex;
...

void *thread1(void *t) {
  while (foo<10) {
    // do stuff
  }
  pthread_exit(NULL);
}

void *thread1(void *t) {
  ...
  pthread_mutex_lock(&mutex);
  ...
  foo++;
  ...
  pthread_mutex_unlock(&mutex);
  ...
  pthread_exit(NULL);
}

int main() {
  ...
}
#包括
...
int foo;
pthread_mutex_t mutex;
...
void*thread1(void*t){

而(foo如果你R/W一个值,你应该同步写入和读取,这是因为这会导致不一致的读取,就像在开始时你想读取
foo=0
,但是写入速度更快,所以你会读取
foo=1


在您的上下文中,这段时间内的迭代次数将少于10次,因此它不是线程安全的

如果您使用R/W值,您应该同步写入和读取,这是因为这可能会导致不一致的读取,就像在开始时您希望读取
foo=0
,但是写入速度更快,因此您将读取
foo=1



在您的上下文中,这段时间内的迭代次数将少于10次,因此它不是线程安全的,因为各种可能的原因,它不是线程安全的,但是您可能会遇到的一个原因是编译器可以很好地将
foo
的读取优化为从while l提升出来的单个读取oop所以它永远看不到更改。

由于各种可能的原因,它不是线程安全的,但您可能会遇到的一个原因是编译器可以很好地将
foo
的读取优化为从while循环中提升出来的单个读取,所以它永远看不到更改。

我认为您需要同时锁定读取和写入。如果不这样做,则可能会出现“脏读”。您的示例不清楚,因为您显示了两个函数
thread1()
。您可能打算使用
thread1()
thread2()
,或类似的内容。不能保证写入通常是原子的,因此您需要使用互斥锁来保护对
foo
的访问。如果
foo
是一种结构类型,这将是一个更严重的问题。但唯一安全的(sane)策略是在读取或写入共享变量之前锁定互斥体。我认为您需要同时锁定读取和写入。如果不锁定,则可能存在“脏读”。您的示例不清楚,因为您显示了两个函数
thread1()
。您可能打算使用
thread1()
thread2()
,或类似的内容。不能保证写入通常是原子的,因此您需要使用互斥锁来保护对
foo
的访问。如果
foo
是一种结构类型,这将是一个更严重的问题。但唯一安全的(sane)策略是在读取或写入共享变量之前锁定互斥体。但我不确定这在我的应用程序中是否是一个问题……我不关心
while
循环有多少次迭代-只是当
foo
真的
>=10
时它就会退出。更重要的是,不锁定互斥体进行读取可能是一个漏洞能够读一些无意义的东西,比如某个东西的空内存插槽……我已经解释了为什么不使用互斥使“读一些无意义的东西”我不明白你是怎么解释的……如果写得更快,我读到foo=1,那不是问题——它只是意味着现在foo=1。如果我读到foo=2981232391(某种类型的坏内存访问),问题就会出现如果不一致的数据不是问题,那么如果foo被初始化,它将不会读取任何垃圾内存结果。但我的回答是,因为你要求线程安全,而它不是线程安全,我不确定这在我的应用程序中是否是一个问题……我不关心
while
循环有多少次迭代-只是它在
foo时退出
实际上是
=10
。更重要的是,不锁定互斥体进行读取可能会容易读取一些无意义的内容,例如某个内容的空内存插槽……我已经解释了不使用互斥体如何使“读取一些无意义”我不明白您在哪里解释了它……如果写入速度更快,并且读取foo=1,这不是问题——它是st表示现在foo=1。如果我以某种方式读取foo=2981232391(某种类型的坏内存访问),则会出现问题如果不一致的数据不是问题,那么如果foo被初始化,它将不会读取任何垃圾内存结果。但我的回答是,因为你要求线程安全,而这不是线程安全有趣的一点。编译器对可以应用于受互斥体保护的对象的优化级别有什么限制?我不知道所有的限制有很多因素可能会起作用,但最主要的是对获取互斥的函数的调用将导致编译器必须重新加载变量,因为据编译器所知,该变量可能已被函数修改。有趣的一点..编译器对优化级别有哪些限制at可以应用于受互斥体保护的对象吗?我不知道可能起作用的所有因素,但主要因素是对获取互斥体的函数的调用将导致编译器必须重新加载变量,因为据编译器所知,变量可能已被函数修改。