You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何全局变量n_segments在多线程环境下值不一致?

问题

我编写了一个C语言多线程程序,声明了若干全局变量并创建子线程进行交互。主线程中为全局变量n_segments赋值为81,但在子线程的segment_handler函数中读取到的n_segments值却为0。既然全局变量本应在多线程间共享,请问为何会出现这种值不一致的情况?

程序代码

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <assert.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/syscall.h>

typedef struct zip_seg zip_seg_t;
typedef struct stat stat_t;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

char **file_ptr;
char *segment_ptr;
stat_t *stat_buf;

struct zip_seg {
    char *data;
    size_t size;
};

int index_cur_file = 0, index_cur_segment = 0;
int n_segments;
int total_segments_cur_file = 0;
int segment_size = 100;
zip_seg_t *zip_list;
    
void* segment_handler() {   
    int size;
    pid_t x = syscall(__NR_gettid);
    //printf("ID %d getting in...\n", x);
    while(1) {
        pthread_mutex_lock(&lock);
        if(index_cur_segment >= n_segments) {
            pthread_mutex_unlock(&lock);
            break;
        }
        if((total_segments_cur_file * segment_size) < stat_buf[index_cur_file].st_size) {
            size = stat_buf[index_cur_file].st_size - (total_segments_cur_file * segment_size);
            index_cur_file++;
            total_segments_cur_file = 0;
            segment_ptr = file_ptr[index_cur_file];
        }
        else {
            size = segment_size;
            total_segments_cur_file++;
            segment_ptr += size;
        }
        int i = index_cur_segment++;
        pthread_mutex_unlock(&lock);
        zip_list[i] = wzip(segment_ptr, size);
        //index_cur_segment++;
    }
    //printf("ID %d getting out...\n", x);
}

int main(int argc, char *argv[])
{
    char c;
    int dummy;
    while((c = getopt(argc, argv, "s:")) != -1) {
        switch(c) {
        case 's':
            dummy = atoi(optarg);
            break;
        }
    }
    
    int n_segments = 0;
    int n_files = argc - optind;
    int n_threads = get_nprocs();
    int fd[n_files];
    file_ptr = malloc(n_files * sizeof(*file_ptr));
    stat_buf = malloc(n_files * sizeof(*stat_buf));
    pthread_t *workers = malloc(n_threads * sizeof(*workers));
    if(!file_ptr || !stat_buf || !workers) {
        printf("Memory allocation error.\n");
        return -1;
    }
    for (int i = 0; i < n_files; i++)
    {
        char *file_name = argv[optind];
        fd[i] = open(file_name, O_RDONLY);
        fstat(fd[i], &stat_buf[i]);
        file_ptr[i] = mmap(NULL, stat_buf[i].st_size, PROT_READ, MAP_PRIVATE, fd[i], 0);
        int extra_segment = (segment_size % stat_buf[i].st_size) > 0 ? 1 : 0;
        n_segments += (stat_buf[i].st_size / segment_size) + extra_segment;
    }
    zip_list = malloc(n_segments * sizeof(*zip_list));
    if(!zip_list) {
        printf("Memory allocation error.\n");
        return -1;
    }

    for (int i = 0; i < n_threads; ++i)
    {
        pthread_create(&workers[i], NULL, segment_handler, NULL);       
    }
    for (int i = 0; i < n_threads; ++i)
    {       
        pthread_join(workers[i], NULL);
    }

    join();

    for (int i = 0; i < n_files; i++)
    {
        munmap(file_ptr[i], stat_buf[i].st_size);
    }
    free(file_ptr);
    free(stat_buf);
    free(workers);
    free(zip_list);

    return 0;
}

附图说明

  • 图1:主线程中n_segments的值为81
  • 图2:子线程中n_segments的值为0

原因分析与解决方案

核心问题

你在main函数中重新声明了一个局部变量n_segments:

int n_segments = 0;

这个局部变量会屏蔽全局作用域的n_segments。主线程中后续对n_segments的赋值操作,都是在操作这个局部变量,而非全局变量。而子线程的segment_handler函数访问的是全局的n_segments,它的初始值是0(全局变量未显式初始化时默认初始化为0),所以会出现值不一致的情况。

修复方法

删除main函数中局部的n_segments声明,直接使用全局变量即可:

// 去掉这一行:int n_segments = 0;
n_segments = 0; // 改为直接对全局变量赋值初始化

额外注意事项

  • 虽然全局变量在多线程间共享,但如果存在多个线程同时读写全局变量,必须保证操作的原子性(你已经用pthread_mutex_t做了同步,这部分是正确的)。
  • 局部变量和全局变量同名时,局部作用域的变量优先级更高,这种“变量遮蔽”问题很容易被忽略,编写代码时要注意避免。

内容的提问来源于stack exchange,提问作者EmTor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 03:12:05