4 并发面向对象技术
并行计算是未来计算机的发展方向。将面向对象与并行计算的相结合的并发面向对象技术是一个比较新的研究领域,许多问题有待解决。
目前一些流行的面向对象程序设计语言(如C++)只提供了描述程序顺序执行的能力;即使有些语言(如Smalltalk)提供了描述程序并发执行的机制,但往往采用一些传统的并发控制模式和设施,没有从对象模型本身的特点来考虑并发控制,从而造成并发与对象模型中一些概念(如封装、继承及自治等)相冲突。
近年来,许多面向对象并发编程的方案被提出,可归纳为3种不同方法:
1. 设计全新的并发面向对象语言;
2. 扩展现存的顺序面向对象语言;
3. 使用现有的顺序面向对象语言,通过外部库提供并发抽象。
并发类库正成为并发面向对象技术中最为重要的方法。这种方法的优点是不需要修改原有顺序面向对象语言,保留原有编程方法,可以更好地利用面向对象技术中的一些特性,用户容易接受。
为了在面向对象模型中引进并发机制,并发类库的设计必须能与对象模型中一些现有的特性有机结合,为面向对象程序设计语言扩展描述系统并发行为的能力。此外,这种方法一般还需要某种底层特殊软件(运行支撑系统)的支持,并将支撑系统的复杂性全部隐藏在类库中。
顺序对象模型由一组被动的对象构成。系统的执行行为是,外界激活其某个对象的某个方法,该方法的执行中向系统中其他对象发送消息,从而激活这些对象的方法的执行。这里的消息发送就是过程调用,即消息发送者必须等到消息接受者的相应方法执行完毕,才能继续执行下去,整个系统只有一个执行线程(Thread)。
在面向对象的并发模型中,可并发执行的基本单位是对象,称为并发对象。与普通对象不同的,并发对象具有自己的控制线索和独立的地址空间,多个并发对象可以并发运行,通过方法(消息传递)请求相互作用。目前存在两种构造并发对象的典型方案:
1. 采用异步消息发送。即一个对象向另一个对象发送消息后,前者不必等待后者处理消息即可继续执行下去,后者则对消息进行缓存;
2. 对象可以有一个体(Body),一旦对象被创建,这个体就开始执行。
在方案1中,由异步消息发送产生新的执行线程,从而引起系统的并发。由于采用异步消息发送,必须提供今后如何取得返回值的设施。异步消息发送的不足之处在于:它使得程序的行为难以把握,不利于对程序的推理(Reasoning)。
方案2通过创建新对象产生新的执行线程,在对象体执行的同时,对象还可以接收和发送消息,消息发送可采用同步方式,但应允许对象内部的并发,否则容易造成死锁。
处于并发环境中的对象,随时都会面临环境对其方法的并发调用。为了保证对象状态的一致性与完整性,必须对方法的并发调用加以同步控制。同步控制可以由消息发送者执行,也可以由消息接受者执行。但是,若同步控制仅由消息发送者执行,当消息发送者由于种种原因没有进行同步控制时,将会产生对消息接受者方法的并发调用,造成消息接受者内部状态的不一致与不完整。因此,消息接受者本身必须提供同步控制。
并发对象的同步控制可以分成两类:条件同步和互斥。条件同步是指对象在某种状态下只能接受某些消息;互斥是指当处于某种状态下的对象可以接受(处理)多个消息时,由于这些消息的处理都有可能使用对象的成员变量,如果让它们同时执行,就存在共享对象的成员变量问题,为了保证对象状态的完整性和一致性,这些方法必须互斥地使用共享变量。
如何在并发对象类中描述对象的同步控制,一般存在两种方式:集中控制和分散控制。
集中控制方式是把对象的同步控制放在对象(类)中某一个地方集中进行描述。这种方式要求设计者必须对对象的并发行为有整体的了解,还有可能带来继承异常,即在定义子类时,必须对父类的同步控制描述进行重定义,才能把新定义的方法考虑进来。
分散控制方式是把对象的并发控制描述分布到对象的各方法上。其中一种方案是在对象各方法的实现中进行同步控制,对象无条件地接收消息,在消息的处理方法中,根据对象目前的状态决定是等待还是继续执行。这种方案的不足之处在于:被挂起的方法往往使得对象处于一种不稳定状态,使得对象此时不适合于处理其他消息;并且当在子类中改变父类某方法的同步控制时,需对整个方法重定义。另一种方案是在对象类中给每个方法加一个激励条件,当对象接收到消息时,将根据相应方法的激励条件来决定是否处理该消息,对不满足激励条件的消息让其等待。这种方案优于前一种方案,因为,当定义子类时可以对父类中各方法的激励条件和方法的实现分开进行继承,从而避免了不必要的重定义。
|