=============
== Pullock ==
=============
脚踏实地

Java基础之Mutex介绍

为了更好的学习Java中的AQS,先回顾下基础知识mutex互斥锁。

互斥锁的定义

在多线程编程中,为了防止多个线程同时对临界区代码进行访问,操作系统引入了互斥锁。对于临界区代码的访问,同一时刻只能有一个线程进行。

互斥锁的实现原理

互斥锁可以理解为是一个整形变量和两个操作(加锁和解锁)构成的锁。

互斥锁只有两个状态:

  • 未加锁状态
  • 加锁状态

互斥锁加锁的实现逻辑:先判断锁的状态,如果是未加锁状态,则将锁改为加锁状态,并返回成功;如果是已加锁状态,则挂起等待。

互斥锁解锁的实现逻辑:直接将锁改为未加锁状态,并唤醒那些挂起等待的的线程。

互斥锁的底层支持

在互斥锁的加锁和解锁实现逻辑中可以看到,加锁和解锁过程中是有多个步骤的,这需要操作系统保证互斥锁操作的原子性。

CPU提供的支持有:

  • 提供原子操作(Test And Set)
  • 关闭中断
  • 锁内存总线

操作系统利用CPU提供的支持,就可以实现互斥锁。

互斥锁的使用

互斥锁的加锁和解锁只能由同一个线程进行操作。

Mutex和优先级反转问题

优先级反转是指:一个低优先级的任务持有一个共享资源,一个高优先的任务也需要持有该共享资源,但此时共享资源被低优先级的任务持有,故高优先级的任务需要阻塞等待低优先级的任务释放资源,而在这个过程中,有一个中优先级的任务(这个任务不需要持有该共享资源)到来,抢占了CPU时间,这样就导致中优先级的任务先执行了,甚至可能会导致高优先级的任务无法执行。

解决优先级反转的方案有:

  • 优先级继承,当一个低优先级的任务持有资源,此时高优先级任务等待低优先级任务完成时,将低优先级任务的优先级调整为高优先级任务的优先级,等低优先级任务释放共享资源后,再回到原来的优先级。
  • 设置优先级上线,给访问共享资源的任务一个高优先级。
  • 禁止中断

实时操作系统上,如果需要互斥保护,进行使用mutex,而不是semaphore,因为semaphore一般没有优先级继承,会导致优先级反转。

参考