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

C语言线程编程:非全局方式安全共享缓冲区与互斥锁

问题描述

我正在编写一个C程序,需要在两个线程之间共享一块缓冲区,同时为保证线程安全,还需使用mutex(互斥锁)。由于线程创建时只能传递一个指针参数,我尝试将互斥锁复制到缓冲区中传递给线程,但线程取出互斥锁后,与主线程的互斥锁失去了关联。

我希望线程锁定互斥锁时能阻塞主线程,以此验证线程同步的有效性,但当前主线程会无限循环运行。以下是我的代码:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<stdbool.h>

#define BUFF 1024

void *func(void *buffer) {
    pthread_mutex_t lock;
    memcpy(&lock, buffer, sizeof(pthread_mutex_t));
    pthread_mutex_lock(&lock); //example
    // do stuff with buffer
}

int main() {
    pthread_mutex_t lock;
    if (pthread_mutex_init(&lock, NULL) != 0) {
        printf("error in mutex init\n");
        return 1;
    }

    void *sharedBuffer = calloc(1, BUFF);
    memcpy(sharedBuffer, &lock, sizeof(pthread_mutex_t));
    pthread_t handle;

    pthread_create(&handle, NULL, func, sharedBuffer);
    while (true) {
        if (pthread_mutex_trylock(&lock) == 0) {
            printf("in main\n");
            if (*(int*)sharedBuffer != 0) {
                //do stuff with shared buffer
            }
            pthread_mutex_unlock(&lock);
        }
    }
}

请问在C语言中,不使用全局变量的前提下,有没有正确共享缓冲区和互斥锁的方法?


解决方案

问题的核心在于互斥锁不能通过复制的方式共享——你在主线程里把互斥锁memcpy到缓冲区,线程里又memcpy出来创建了一个新的互斥锁实例,这两个锁完全独立,自然无法实现同步。

正确的做法是把互斥锁和缓冲区封装到一个结构体里,然后传递这个结构体的指针给线程,让两个线程共享同一个结构体实例(也就是同一个互斥锁和缓冲区)。

修改后的代码示例

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <unistd.h>

#define BUFF_SIZE 1024

// 封装共享资源的结构体
typedef struct {
    pthread_mutex_t lock;
    char buffer[BUFF_SIZE];
} SharedData;

void *func(void *arg) {
    SharedData *data = (SharedData*)arg;
    
    // 锁定共享的互斥锁
    pthread_mutex_lock(&data->lock);
    printf("子线程已锁定互斥锁\n");
    // 操作共享缓冲区
    strcpy(data->buffer, "hello from thread");
    // 模拟耗时操作,验证主线程是否阻塞
    sleep(2);
    pthread_mutex_unlock(&data->lock);
    printf("子线程已解锁互斥锁\n");
    
    return NULL;
}

int main() {
    // 分配并初始化共享结构体
    SharedData *sharedData = malloc(sizeof(SharedData));
    if (!sharedData) {
        perror("malloc failed");
        return 1;
    }
    
    // 初始化互斥锁
    if (pthread_mutex_init(&sharedData->lock, NULL) != 0) {
        printf("互斥锁初始化失败\n");
        free(sharedData);
        return 1;
    }
    
    // 初始化缓冲区
    memset(sharedData->buffer, 0, BUFF_SIZE);
    
    pthread_t handle;
    pthread_create(&handle, NULL, func, sharedData);
    
    while (true) {
        if (pthread_mutex_trylock(&sharedData->lock) == 0) {
            printf("主线程已锁定互斥锁\n");
            if (strlen(sharedData->buffer) > 0) {
                printf("缓冲区内容:%s\n", sharedData->buffer);
            }
            pthread_mutex_unlock(&sharedData->lock);
            // 退出循环,避免无限运行
            break;
        } else {
            printf("主线程尝试锁定失败,等待子线程解锁...\n");
            sleep(1);
        }
    }
    
    // 等待子线程结束
    pthread_join(handle, NULL);
    // 销毁互斥锁
    pthread_mutex_destroy(&sharedData->lock);
    // 释放内存
    free(sharedData);
    
    return 0;
}

关键说明

  • 结构体封装:把互斥锁和缓冲区放在同一个结构体中,确保两者的生命周期一致,且能通过同一个指针传递给线程。
  • 共享指针而非复制:线程接收的是结构体的指针,操作的是同一个互斥锁实例,这样锁定/解锁操作才能在两个线程间同步。
  • 资源清理:使用完后要销毁互斥锁并释放结构体内存,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 07:20:53