线程通信 - 互斥
- 一次只允许一个任务(进程、线程)访问的共享资源。
- 正在访问临界资源的代码段,其他代码段叫非临界区。
要想实现对临界资源的保护,最主要的一点就是要求每个线程的临界区是互斥的(若A线程和B线程都会访问同一个临界资源,当A线程在运行访问这个资源的临界区代码的时候,B线程就不能运行访问这个资源的临界区代码)。
- 任务访问临界资源前线获取临界资源对应的互斥锁,访问完临界资源再释放互斥锁。
- 互斥锁同一时刻只能被一个线程持有,也就是最大只有1的信号量。
- 通过互斥锁就可以实现在某一时刻最多只有一个线程在执行临界区,访问互斥资源。
- 当一个线程需要进入临界区的时候,需线获取资源对应的互斥锁,如果获取不到该资源的互斥锁就必须阻塞等待互斥锁被释放。
互斥锁初始化:
1 |
|
申请锁、加锁、上锁:
1 | tinclude <pthread.h> |
释放锁:
1 |
|
如果有两个里捏资源只会在同一时刻同时被访问,那么就可以只用一个互斥锁来保护这两个临界资源,如果两个连接资源会在不同的时候被访问,那么就需要两个互斥锁来分别保护这两个临界资源。
互斥锁示例:

代码:
1 | unsigned int count, value1, value2; |
运行结果:
1 | //不使用互斥锁,会出现value1和value2不想等的情况 |
补充知识
死锁产生情况:
同一个线程对对同一个互斥锁二次加锁,此线程持有互斥锁被永远阻塞。
线程A在持有部分互斥锁时,阻塞等待获取线程B已经持有的互斥锁,并且线程B恰好也在阻塞等待被线程A持有的互斥锁被释放。
避免死锁出现的方法:
- 理清程序逻辑,避免出现线程对一个互斥锁二次加锁。 在对一个互斥锁加锁前先检测它是否被线程持有,如果该线程就是自己就不要再尝试对该互斥锁加锁。
- 统一系统中各个线程对资源访问的顺序,这样每个线程对互斥锁的访问顺序也就相同了,避免出现两个线程互相持有部分互斥锁的情况。
- 当一个线程需要持有多个互斥锁去访问临界资源的时候,如果已经获取了部分互斥锁,等待其它的互斥锁超时时(加锁时设置超时时间),就把自己持有的这部分互斥锁释放掉。
- RTOS中的信号量:
二值信号量:用于线程间同步,用于表示资源可访问或者资源不可访问,值为0或1
计数信号量:用于表示某个资源的数量,值是正整数
互斥锁:在二值信号量的基础上 1.增加记录线程对锁的加锁次数,加锁几次就要解锁几次,防止上面所说的死锁出现。 2.增加防止优先级翻转的机制,所以RTOS互斥锁也称递归互斥量。
线程中记录有基优先级和当前优先级,当一个线程要获取一个互斥锁发现该互斥锁正在被一个比自己低的优先级的线程占用时,就会把占有互斥锁线程的当前优先级提高到和自己相等的优先级,线程在释放互斥锁的时候会比较当前优先级和基优先级,如果当前优先级比基优先级大就把当前优先级恢复成基优先级。
- 本文作者: 龙兄嵌入式
- 本文链接: https://hexo.880755.xyz/1970/01/01/zblog/download/41.线程间通信 - 互斥锁/