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

如何控制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(&... // 初始化代码不完整
}

存在的问题:

  1. 类型拼写错误:pthread_mutext_t是错误的,正确的互斥锁类型是pthread_mutex_t(把mutex误写为mutext)。
  2. 初始化不完整:pthread_mutex_init的调用未完成,正确写法是pthread_mutex_init(&mutx, NULL);。
  3. 线程创建与回收缺失:main函数仅声明了线程数组,但未调用pthread_create创建线程,也没有用pthread_join等待线程执行完毕——这会导致main提前退出,线程可能未完成任务就被终止。
  4. 循环逻辑缺陷: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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:06:36