如何控制Mutex互斥锁的加锁与解锁?附基础示例代码疑问
关于POSIX Mutex互斥锁加解锁的控制与代码问题解答
嘿,我来帮你梳理清楚POSIX Mutex互斥锁的加解锁控制逻辑,同时解决你给出的示例代码里的问题~
一、Mutex互斥锁的核心加解锁操作
Mutex的核心就是通过加锁保护临界区(多个线程共享的资源或代码块),解锁释放资源让其他线程可以访问,具体操作如下:
- 加锁:使用
pthread_mutex_lock(&mutex),这个函数会阻塞当前线程,直到成功获取到互斥锁;如果不想阻塞等待,可以用pthread_mutex_trylock(&mutex)——尝试加锁失败会直接返回错误码,线程可以继续执行其他逻辑。 - 解锁:必须由持有该锁的线程调用
pthread_mutex_unlock(&mutex),如果非持有锁的线程调用,行为是未定义的(可能导致程序崩溃、死锁等问题)。 - 初始化与销毁:使用前必须通过
pthread_mutex_init(&mutex, NULL)初始化(NULL表示使用默认属性);使用完毕后要调用pthread_mutex_destroy(&mutex)释放系统资源,避免内存泄漏。
二、你的示例代码中的问题分析
先把你给出的代码贴出来,我们逐一排查问题:
#include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #define TNUM 4 pthread_mutext_t mutx; // 这里有拼写错误 int cnt = 0; void *t_function(void *data) { while(cnt < 1000) { pthread_mutex_lock(&mutx); cnt++; pthread_mutex_unlock(&mutx); } } int main() { pthread_t p_thread[TNUM]; int thr_id[TNUM]; int status; int i; clock_t start, end; status = pthread_mutex_init(&... // 初始化代码不完整 }
存在的问题:
- 类型拼写错误:
pthread_mutext_t是错误的,正确的互斥锁类型是pthread_mutex_t(把mutex误写为mutext)。 - 初始化不完整:
pthread_mutex_init的调用未完成,正确写法是pthread_mutex_init(&mutx, NULL);。 - 线程创建与回收缺失:main函数仅声明了线程数组,但未调用
pthread_create创建线程,也没有用pthread_join等待线程执行完毕——这会导致main提前退出,线程可能未完成任务就被终止。 - 循环逻辑缺陷:
while(cnt < 1000)的判断在加锁外,当cnt接近1000时,多个线程可能同时进入循环,导致cnt最终超过1000(比如cnt=999时,3个线程都进入循环,加锁后各自执行cnt++,最终cnt会变成1002)。
三、修正后的完整代码
下面是修复所有问题后的代码,附带详细注释:
#include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <time.h> #define TNUM 4 pthread_mutex_t mutx; // 修正拼写错误 int cnt = 0; void *t_function(void *data) { while(1) { pthread_mutex_lock(&mutx); // 先加锁,再操作临界资源 if (cnt >= 1000) { pthread_mutex_unlock(&mutx); // 退出循环前必须解锁,避免死锁 break; } cnt++; printf("Thread %ld: 当前cnt = %d\n", (long)data, cnt); // 打印线程ID和当前值,方便观察 pthread_mutex_unlock(&mutx); // 解锁,让其他线程可以访问cnt usleep(100); // 模拟实际工作负载,避免线程无意义地抢锁 } return NULL; } int main() { pthread_t p_thread[TNUM]; int thr_id[TNUM]; int status; long i; // 用long作为线程参数,避免类型转换问题 clock_t start, end; // 初始化互斥锁,添加错误检查 status = pthread_mutex_init(&mutx, NULL); if (status != 0) { perror("pthread_mutex_init 失败"); exit(EXIT_FAILURE); } start = clock(); // 记录开始时间 // 创建TNUM个线程 for (i = 0; i < TNUM; i++) { thr_id[i] = pthread_create(&p_thread[i], NULL, t_function, (void *)i); if (thr_id[i] != 0) { perror("pthread_create 失败"); exit(EXIT_FAILURE); } } // 等待所有线程执行完毕 for (i = 0; i < TNUM; i++) { status = pthread_join(p_thread[i], NULL); if (status != 0) { perror("pthread_join 失败"); exit(EXIT_FAILURE); } } end = clock(); // 记录结束时间 printf("\n最终cnt值: %d\n", cnt); printf("总耗时: %lf 秒\n", (double)(end - start)/CLOCKS_PER_SEC); // 销毁互斥锁,释放资源 pthread_mutex_destroy(&mutx); return 0; }
修正点说明:
- 修复了互斥锁类型的拼写错误
- 补全了互斥锁的初始化、销毁逻辑,并添加错误检查,方便排查问题
- 添加了线程创建和回收代码,确保所有线程完成任务后main才退出
- 将循环判断移到锁内部,彻底避免cnt超过1000的情况
- 增加打印和延迟,让线程的执行行为更直观,同时避免无意义的锁竞争
内容的提问来源于stack exchange,提问作者hyojoon
相关产品推荐
相关产品推荐

