跳转到内容

C 语言互斥锁

来自代码酷

C语言互斥锁[编辑 | 编辑源代码]

互斥锁(Mutex,全称 Mutual Exclusion)是C语言多线程编程中用于保护共享资源的核心同步机制。它确保同一时间只有一个线程能访问临界区(Critical Section),从而防止数据竞争(Data Race)和竞态条件(Race Condition)。

基本概念[编辑 | 编辑源代码]

互斥锁的工作原理可类比为「厕所门锁」:

  • 线程进入临界区前必须获取锁(锁定)
  • 执行完成后释放锁(解锁)
  • 其他线程必须等待锁释放才能进入

数学表达为: {Lock:if(mutex == 0) mutex = 1;Unlock:mutex = 0;

POSIX线程库实现[编辑 | 编辑源代码]

C语言通过`pthread_mutex_t`类型实现互斥锁:

#include <pthread.h>

// 声明互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* thread_func(void* arg) {
    pthread_mutex_lock(&mutex);  // 加锁
    // 临界区代码
    pthread_mutex_unlock(&mutex); // 解锁
    return NULL;
}

完整示例[编辑 | 编辑源代码]

模拟银行账户转账操作:

#include <stdio.h>
#include <pthread.h>

int balance = 1000; // 共享资源
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* transfer(void* amount) {
    int amt = *(int*)amount;
    
    pthread_mutex_lock(&mutex);
    if(balance >= amt) {
        balance -= amt;
        printf("转账 %d 成功,余额: %d\n", amt, balance);
    } else {
        printf("余额不足!\n");
    }
    pthread_mutex_unlock(&mutex);
    
    return NULL;
}

int main() {
    pthread_t t1, t2;
    int amount1 = 600, amount2 = 700;
    
    pthread_create(&t1, NULL, transfer, &amount1);
    pthread_create(&t2, NULL, transfer, &amount2);
    
    pthread_join(t1, NULL);
    pthread_join(t2, NULL);
    
    printf("最终余额: %d\n", balance);
    return 0;
}

输出示例:

转账 600 成功,余额: 400
余额不足!
最终余额: 400

互斥锁类型[编辑 | 编辑源代码]

POSIX提供多种互斥锁类型:

类型 描述
PTHREAD_MUTEX_NORMAL 标准互斥锁(不检测死锁)
PTHREAD_MUTEX_ERRORCHECK 错误检查锁(检测递归锁定)
PTHREAD_MUTEX_RECURSIVE 可递归锁(允许同一线程多次加锁)
PTHREAD_MUTEX_DEFAULT 系统默认类型

死锁预防[编辑 | 编辑源代码]

互斥锁使用不当会导致死锁,常见场景:

  • 线程A持有锁1请求锁2
  • 线程B持有锁2请求锁1

解决方法:

  • 固定加锁顺序
  • 使用`pthread_mutex_trylock()`
  • 设置超时等待

性能考量[编辑 | 编辑源代码]

互斥锁会引入性能开销,优化策略包括:

  • 减小临界区范围
  • 使用读写锁(`pthread_rwlock_t`)替代
  • 考虑无锁编程(Lock-free)方案

实际应用场景[编辑 | 编辑源代码]

1. 数据库连接池:管理有限连接资源 2. GUI事件处理:防止界面更新冲突 3. 游戏引擎:同步物理引擎与渲染线程

状态转换图[编辑 | 编辑源代码]

stateDiagram-v2 [*] --> Unlocked Unlocked --> Locked: pthread_mutex_lock() Locked --> Unlocked: pthread_mutex_unlock() Locked --> Locked: 其他线程等待

常见错误[编辑 | 编辑源代码]

  • 忘记解锁导致死锁
  • 在临界区内调用可能阻塞的函数
  • 不同线程以不同顺序获取多个锁

进阶话题[编辑 | 编辑源代码]

  • 条件变量(`pthread_cond_t`)与互斥锁配合使用
  • 自旋锁(`pthread_spinlock_t`)在短等待时的应用
  • C11标准引入的`mtx_t`类型

互斥锁是多线程编程的基础工具,正确使用可以构建线程安全的应用程序,但需要开发者谨慎处理锁的获取和释放顺序。