【问题标题】:child thread does not see effect of increment by main thread子线程看不到主线程增加的效果
【发布时间】:2022-01-12 00:15:44
【问题描述】:

我正在使用 POSIX 线程处理 C 网络应用程序。我遇到了一个问题,即用作监视器的子线程未检测到主线程对全局计数器所做的更改(增量)。我设法将相关代码提取到以下3个文件中并重现了问题。

// common.h
#ifndef COMMON_H
#define COMMON_H
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
#include <sys/resource.h>
static volatile int glob = 0;
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void increment_clients_count();

#endif
// common.c
#include "common.h"

void increment_clients_count()
{
        // Lock
        pthread_mutex_lock(&mutex);     
        glob++;
        // Unlock
        pthread_mutex_unlock(&mutex);
}
// thread_incr_wrong.c 
// main function
#include "common.h"

void                    /* Loop 'arg' times incrementing 'glob' */
monitor()
{
    while(1)
    {        
        time_t current_time;
        time(&current_time);
        char *t = ctime(&current_time);
        if (t[strlen(t)-1] == '\n') t[strlen(t)-1] = '\0';
        printf("%s, Count : %d\n", t, glob);
        sleep(3);
    }

}


int
main(int argc, char *argv[])
{
    pthread_t t1;   
    int s;
   

    s = pthread_create(&t1, NULL, (void*)monitor, NULL);
    if (s != 0){
        perror("pthread_create");
        exit(1);
     }
    
    while(1){        
        increment_clients_count();        
        sleep(5);
    }

    
    exit(0);
}

当这条鳕鱼运行时,我希望看到

Tue Jan 11 18:56:24 2022, Count : 1
Tue Jan 11 18:56:27 2022, Count : 1
Tue Jan 11 18:56:30 2022, Count : 2
Tue Jan 11 18:56:33 2022, Count : 2
Tue Jan 11 18:56:36 2022, Count : 3
Tue Jan 11 18:56:39 2022, Count : 4
Tue Jan 11 18:56:42 2022, Count : 4
Tue Jan 11 18:56:45 2022, Count : 5
Tue Jan 11 18:56:48 2022, Count : 5
Tue Jan 11 18:56:51 2022, Count : 6
Tue Jan 11 18:56:54 2022, Count : 7

相反,输出看起来像这样

Tue Jan 11 18:59:40 2022, Count : 0
Tue Jan 11 18:59:43 2022, Count : 0
Tue Jan 11 18:59:46 2022, Count : 0
Tue Jan 11 18:59:49 2022, Count : 0
Tue Jan 11 18:59:52 2022, Count : 0

监视器线程没有看到 glob 变量每 5 秒递增一次。

请让我知道我在代码中哪里做错了。

如果您想尝试重现问题,可以复制这 3 个文件并使用 cc -std=c99 -D_XOPEN_SOURCE=600 -D_DEFAULT_SOURCE -g -pedantic -Wall -W -Wmissing-prototypes -Wno-sign-compare -Wimplicit-fallthrough -Wno-unused-parameter -pthread -o thread_incr_wrong thread_incr_wrong.c common.c 在任何 Linux 机器上。可执行文件的名称是 thread_incr_wrong

谢谢

【问题讨论】:

  • 旁注:monitor() 应该在读取glob 的值之前获取互斥锁,然后释放互斥锁。

标签: c multithreading posix


【解决方案1】:

globmutex 都声明为 static。这意味着当 common.h 包含在 common.c 和 main.c 中时,它们每个都有自己的这些变量的副本。

全局变量应该声明在所有源文件都可以看到的头文件中,并且定义在一个源文件中。因此,将标头中的内容更改为外部声明并将定义放在 common.c 中:

common.h:

extern volatile int glob;
extern pthread_mutex_t mutex;

common.c:

volatile int glob = 0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

【讨论】:

  • 谢谢。是的,这是导致错误的静态声明。
  • 请注意,结果仍然是不可预测的,因为从一个线程访问 volatile int 而另一个线程可能正在修改它的结果是由任何相关标准未定义的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-05
  • 2015-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多