☰
自学嵌入式Day29:Linux多线程控制(互斥锁、信号量与死锁)
2026/10/31 2:14:54 网站建设 项目流程

目录

一、线程互斥(Mutex)

1. 核心概念

2. 互斥锁的使用步骤

3. 相关 API 函数

4. 互斥锁的注意事项

二、线程同步(Semaphore)

1. 核心概念

2. 互斥锁 vs 信号量(重点区分)

3. 信号量的使用步骤

4. 相关函数

三、死锁(Deadlock)

1. 什么是死锁?

2. 产生死锁的四个必要条件(缺一不可)


一、线程互斥(Mutex)

1. 核心概念

  • 临界资源:在多线程中,会被多个线程同时进行读写操作的资源(如全局变量、文件、硬件设备等)。

  • 互斥(Mutual Exclusion):在多线程中,对临界资源的排他性访问。即同一时刻,只能有一个线程访问该资源。

2. 互斥锁的使用步骤

定义锁 →→ 初始化锁 →→ 加锁 →→ 解锁 →→ 销毁锁

3. 相关 API 函数

使用互斥锁需包含头文件<pthread.h>。

  1. 定义与初始化
    pthread_mutex_t mutex; // 定义互斥锁 int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr); // 功能:初始化互斥锁。 // 参数:attr 一般传 NULL,表示默认属性。 // 返回值:成功 0,失败 非零。
  2. 加锁
    int pthread_mutex_lock(pthread_mutex_t *mutex); // 功能:加锁。加锁后的代码到解锁部分的代码属于“原子操作”。 // 如果 mutex 已经被其他线程锁住,当前线程会在这里阻塞等待。

    原子操作:在线程的一次调度中,这段代码必须完成,不能中途发生线程调度。

  3. 解锁
    int pthread_mutex_unlock(pthread_mutex_t *mutex); // 功能:解锁。解锁后代码不再排他访问。
  4. 销毁
    int pthread_mutex_destroy(pthread_mutex_t *mutex); // 功能:使用完毕后销毁锁,释放资源。

4. 互斥锁的注意事项

  1. 谁加锁,谁解锁:互斥锁的加锁和解锁必须在同一个线程中进行。
  2. 临界区要“短小精悍”:在被互斥锁保护的代码段(临界区)内,绝对不要执行休眠(sleep)或耗时极长的操作,否则会导致其他线程长时间阻塞,严重影响并发效率。

二、线程同步(Semaphore)

1. 核心概念

  • 同步:有一定先后顺序的对资源的排他性访问。
  • 关系:互斥包含同步,同步是互斥的一个特例。

2. 互斥锁 vs 信号量(重点区分)

  1. 持有者:互斥锁有持有者的概念(谁加锁谁解锁);信号量没有持有者,可以由线程 A 释放、线程 B 申请(th1 释放 th2,th2 释放 th1,交叉释放)。
  2. 临界区限制:互斥锁保护的临界区不能休眠;而信号量保护的区域适当可以有休眠或小的耗时操作。
  3. 资源数:互斥锁资源唯一;信号量是计数信号量,其初值可以大于 1(适用于有多个相同资源的情况)。

3. 信号量的使用步骤

定义信号量 →→ 初始化 →→ P/V 操作 →→ 销毁。

4. 相关函数

使用信号量需包含头文件<semaphore.h>。

  • 定义与初始化
    sem_t sem; // 定义信号量 int sem_init(sem_t *sem, int pshared, unsigned int value); // 功能:初始化信号量。 // 参数:pshared == 0 表示线程间使用;!=0 表示进程间使用。 // value 是初始值。二值信号量(0 或 1),0表示红灯阻塞,1表示绿灯通行。
  • P/V 操作
    • P 操作(申请资源):对应sem_wait()。如果有资源,申请并执行sem = sem - 1;如果没有资源,阻塞等待。
      int sem_wait(sem_t *sem);
    • V 操作(释放资源):对应sem_post()。释放资源并执行sem = sem + 1,不会阻塞。
      int sem_post(sem_t *sem);
  • 销毁
    int sem_destroy(sem_t *sem);

三、死锁(Deadlock)

1. 什么是死锁?

由于锁资源安排不合理(申请和释放逻辑不对),导致多个进程或线程互相等待对方释放资源,从而无法继续执行(推进)的现象。

2. 产生死锁的四个必要条件(缺一不可)

这是计算机科学中非常经典的考点:

  1. 互斥条件:一个资源每次只能被一个进程使用。
  2. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
  3. 不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
  4. 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

破局之法:我们在写代码时,只要破坏上述四个条件中的任意一个(例如:规定所有线程按相同的顺序申请锁),就可以避免死锁。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询