Java基础之管程介绍
为了更好的学习Java中的AQS,先熟悉下管程以及条件变量相关的知识。
信号量在使用的时候比较繁琐,并且极容易出错。如果想要实现线程间的同步,至少需要三个信号量实例,一个作为锁,两外两个充当条件变量的角色。使用复杂并且易出错,而管程解决了这些问题。
管程的组成
管程在信号量的基础上封装了条件变量和等待队列,还封装了同步操作。管程的组成如下:
- 一个变量,和信号量一样表示状态
- 条件变量和对应的等待队列
- 同步队列
- 条件变量可执行的await方法和signal/signalAll方法
- 加锁和解锁操作
管程模型
管程有三种模型:
- Hasen模型
- Hoare模型
- MESA模型
假设有两个线程t1和t2,t1等待t2的某些操作,使得t1等待的条件成立。
Hasen模型:要求将notify方法放到代码最后,也就是t2执行完后,才通知t1执行,这样就能保证同一时刻只有一个线程执行。
Hoare模型:t2执行,通知t1后,t2马上阻塞,t1执行,等t1执行完后,唤醒t2继续执行。这种模型下t2多了一次阻塞和唤醒操作。
MESA模型:t2执行,通知t1后,t2继续执行,t1不立刻执行,而是从条件变量的等待队列进入到入同步队列。t1需要使用自旋来检测条件变量,看是否满足条件。
管程的例子
Java中的synchronized和AQS都是基于管程模型实现的,使用的是MESA模型。
条件变量
条件变量是用来实现线程间的依赖或等待机制的方法,比如线程A阻塞等待某个条件才能继续执行,线程B的执行使得条件成立,就会唤醒A继续执行。