7-7(1)小记
第八讲-管程,并发编程万能钥匙
背景
Java语言1.5之前,提供的唯一的并发原语就是管程;
定义
管程之管 - 管理共享变量;
管程之程 - 共享变量操作过程;
管程之结果 - 管理类的成员变量和成员方法,让这个类是线程安全的;
发展史
管程模型-Hasen模型、Hoare模型、MESA模型;
管程解决互斥问题
1) 思路 : 将共享变量以及对共享变量的操作统一封装起来;
2)管程X将共享变量queue这个队列和相关的操作入队enq()、出队deq()都封装起来了;
3)线程A、线程B访问共享变量queue,只能调用通过管程提供的enq()、deq()方法来实现;
4)enq()、deq()保证互斥性,只允许一个线程进入管程;
5)由此可见:管程模型和面向对象高度契合;
管程解决同步问题
MESA模型:
1)最外层框代表封装,封装了共享变量V以及对共享变量的操作方法X、方法Y;
2)入口、入口等待队列,代表当多个线程同时试图进入管程内部时,只允许一个线程进入,
其他线程在入口等待队列中等待;
3) 管程中引入了条件变量,每个条件变量都对应有一个等待队列,如下图中的条件变量A,
条件变量B分别有自己的等待队列;
4)利用管程模型实现一个阻塞队列,有入队和出队两个操作,这两个操作都是先获取互斥锁;
假设:
线程T1入队,线程T2出队,根据MESA管程模型,只允许一个线程进入管程;
T1先执行,发现队列已满,无法进行入队操作,则去条件变量notFull对应等待队列等待;
T2后执行,发现队列不空,可以进行出队操作,出队操作成功后,则通知条件变量notFull
对应等待队列,线程T1被唤醒,则可进行入队操作;
因此:
T2通知完T1,T2接着执行,T1并不立即执行,仅仅是从条件变量notFull的等待队列进入
到入口的等待队列,但是,当T1再次执行时,可能曾经满足的条件,现在已经不满足了,
所以需要以循环方式校验条件变量;
总结
Java参考了MESA模型,语言内置的管程(synchronized)对MESA模型进行了精简,MESA模型
中,条件变量可以有多个,Java语言内置的管程里面只有一个条件变量;
Java内置的管程方案使用简单,synchronized修饰的代码块,编译期会自动生成加锁和解锁代
码,但是仅支持一个条件变量;Java SDK并发包实现的管程支持多个条件变量,需要开发人员
自己进行加锁,解锁;