c-子线程看不到主线程增量的影响



我正在使用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] = '';
printf("%s, Count : %dn", 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个文件,并用任何Linux机器上的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。可执行文件的名称为thread_incr_wrong

感谢

globmutex都声明为static。这意味着,当common.h同时包含在common.c和main.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;

最新更新