【问题标题】:Is it thread-safe to read but not write a shared variable?读取但不写入共享变量是否是线程安全的?
【发布时间】:2017-05-08 01:45:58
【问题描述】:

使用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() {
  ...
}

【问题讨论】:

  • 我认为你需要锁定读写。否则,可能会出现“脏读”。
  • 您的示例不清楚,因为您显示了两个函数thread1()。大概,您打算使用thread1()thread2(),或类似的东西。不能保证写入通常是原子的,因此您需要使用互斥锁来保护对foo 的访问,以便读取和写入。如果foo 是结构类型,那将是一个更严重的问题。但唯一安全(理智)的策略是在读取或写入共享变量之前锁定互斥锁。

标签: c multithreading thread-safety pthreads


【解决方案1】:

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

【讨论】:

  • 有趣的一点.. 编译器对可以应用于受互斥体保护的事物的优化级别有什么限制?
  • 我不知道可能起作用的所有各种因素,但主要的是调用获取互斥锁的函数将导致编译器必须重新加载变量,因为据编译器所知,该变量可能已被函数修改。
【解决方案2】:

如果您 R/W 一个值,您应该同步写入和读取,那是因为这会导致读取不一致,例如在开始时您想读取 foo = 0,但写入速度更快,因此您将读取 foo = 1 .

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

【讨论】:

  • 我不确定这是否是我的应用程序中的一个问题......我不在乎while 循环有多少次迭代 - 只是当foo 真的是它时它会退出&gt;=10。更令人担忧的是,不锁定互斥锁以进行读取可能容易读取一些废话,例如某个空的内存插槽......
  • 我已经解释了不使用互斥锁是如何“阅读一些废话”的
  • 我看不出你在哪里解释它...如果写入速度更快并且我读取 foo=1,那不是问题 - 它现在只是意味着 foo=1。如果我以某种方式读取 foo=2981232391 (某种错误的内存访问),就会出现问题
  • 如果不一致的数据不是问题,那么如果 foo 被初始化,它将不会读取任何垃圾内存结果。但我的回答是,因为你要求线程安全,它不是线程安全的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 1970-01-01
  • 2017-10-02
  • 1970-01-01
  • 2013-05-23
  • 1970-01-01
相关资源
最近更新 更多