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
相关产品推荐
相关产品推荐

