c - 多线程编程使用全局变量时出现的奇怪问题

标签 c linux multithreading global-variables

有点奇怪,我的场景如下:

在文件A.c中定义两个全局变量:

volatile bool g_test = true;
pthread_mutex_t g_test_mutex = PTHREAD_MUTEX_INITIALIZER;

在文件 A.c 中,全局变量是只读的。

...
pthread_mutex_lock(& g_test_mutex); 
if(! g_test){
     ret = -1;
     pthread_mutex_unlock(& g_test_mutex);
     goto cleanup;
 }
pthread_mutex_unlock(& g_test_mutex);
...

并且全局变量写在另一个文件B.c中

...
extern volatile bool g_test;
extern pthread_mutex_t g_test_mutex;

bool tmpval = func_to_getval();

if(tmpval != g_test){
   pthread_mutex_lock(& g_test_mutex);
   g_test = tmpval;
   pthread_mutex_unlock(&g_test_mutex);
}
printf("g_test value:%s\n",g_test?"yes":"no");
...

以上代码都OK

但是奇怪的是,去掉最后一句printf,g_test改变后就无法同步成功,文件A.c无法获取到更新后的值,为什么??

更新:

我更改代码:

bool tmpval = func_to_getval();

if(tmpval != g_test){
   pthread_mutex_lock(& g_test_mutex);
   g_test = tmpval;
   pthread_mutex_unlock(&g_test_mutex);
}
printf("g_test value:%s\n",g_test?"yes":"no");

pthread_mutex_lock(&g_can_encrypted_mutex);
g_can_decrypted = func_to_getval(env); 
pthread_mutex_unlock(&g_can_encrypted_mutex);

通过了,但是这样每次都会锁住mutex,使用这种方法会增加多少开销?

最佳答案

B.c 不应该在没有持有 g_test_mutex 的情况下引用 g_test;两个线程可能会争用这段代码,并且因为您在 if 中读取 g_test,然后稍后更新它,所以另一个线程可能会同时进入并更新 g_test。

这意味着这个原始代码是错误的:

if(tmpval != g_test){  // Access to g_test without mutex
   pthread_mutex_lock(& g_test_mutex);
   g_test = tmpval;
   pthread_mutex_unlock(&g_test_mutex);
}

您应该在您持有锁时分配的局部变量中保留 g_test 的副本;然后在释放锁后,在 printf() 中使用该局部。

当并发程序通过改变通信区域之外的时间来改变行为时,寻找竞争条件。

关于c - 多线程编程使用全局变量时出现的奇怪问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48414672/

相关文章:

c++ - 如何通过 QtConcurrent 调用带参数的函数

Python 记录器消息显示在单独的行上

c - 为什么这个缓冲区定义在一个循环内?

c - 使用指针功能 - 1 台设备上的 2 个独立应用程序

c - 对于整数数组 |a|和整数 |i|在 C 中,a[i] 给出与 i[a] 相同的结果

c - fgets 如何从文件中逐行读取?

linux - 在 linux 终端中它说文件存在

multithreading - Spring @Async 限制线程数

linux - 如何停止/杀死以守护进程模式启动的 Airflow 调度程序

linux - 询问收件人、主题和正文的 Bash 邮件脚本