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)由此可见:管程模型和面向对象高度契合;

              7-7(1)小记

 

管程解决同步问题

       MESA模型:

       1)最外层框代表封装,封装了共享变量V以及对共享变量的操作方法X、方法Y;

       2)入口、入口等待队列,代表当多个线程同时试图进入管程内部时,只允许一个线程进入,

             其他线程在入口等待队列中等待;

       3)  管程中引入了条件变量,每个条件变量都对应有一个等待队列,如下图中的条件变量A,

             条件变量B分别有自己的等待队列;

             7-7(1)小记

        4)利用管程模型实现一个阻塞队列,有入队和出队两个操作,这两个操作都是先获取互斥锁;

              7-7(1)小记

              假设:

              线程T1入队,线程T2出队,根据MESA管程模型,只允许一个线程进入管程;

              T1先执行,发现队列已满,无法进行入队操作,则去条件变量notFull对应等待队列等待;

              T2后执行,发现队列不空,可以进行出队操作,出队操作成功后,则通知条件变量notFull

              对应等待队列,线程T1被唤醒,则可进行入队操作;

              因此:

              T2通知完T1,T2接着执行,T1并不立即执行,仅仅是从条件变量notFull的等待队列进入

              到入口的等待队列,但是,当T1再次执行时,可能曾经满足的条件,现在已经不满足了,

              所以需要以循环方式校验条件变量;

              

总结

      Java参考了MESA模型,语言内置的管程(synchronized)对MESA模型进行了精简,MESA模型

      中,条件变量可以有多个,Java语言内置的管程里面只有一个条件变量;

      Java内置的管程方案使用简单,synchronized修饰的代码块,编译期会自动生成加锁和解锁代

      码,但是仅支持一个条件变量;Java SDK并发包实现的管程支持多个条件变量,需要开发人员

      自己进行加锁,解锁;

       7-7(1)小记