第二章在面向对象模型中引进并发 度策略设计的不好,就会出现多个read消息"合谋饿死"write消息的情形。因此,对 象在进行消息接收的调度时,应考虑调度策略的公平性。 2.3对象的并发控制 在并发面向对象模型中,对象间不存在共享变量但存在共享对象。处于并发 环境中的对象随时都会面临环境对其方法的并发调用,如果对方法的并发调用不 进行同步控制,将会造成对象状态的混乱,从而导致整个系统行为的不正确。 如何在对象模型中进行并发控制,一般存在两种途径,即:正交途径和集成 途径。在正交途径中,系统的并发执行与对象分开考虑,对象本身不提供并发控 制,而是在对象的方法中显式地采用传统的同步机制(如:信号量等)来控制系统的 并发与同步,并发控制可以在消息发送方的方法中进行,也可以在消息接受方的 方法中完成。正交途径只是在传统并发程序设计基础上加上了对象这个框架,并 没有从面向对象模型本身的特点来考虑并发,一个对象的并发控制要依赖于其它 对象的配合,从而不符合对象所具有的自治性与局部性特点,并且,在对象的方 法中进行并发控制会使得对象类的并发属性难以继承。 集成途径把并发与对象结合起来考虑,对象本身提供并发控制,即,对象对 其方法的并发调用进行同步控制。对象在接收消息时,将根据自身的状态决定是 否处理该消息。 对象是一个高度自治的实体,它应具有自动的自我保护能力,而不应由环境 对其行为有过多的假设。在设计对象类时应考虑外部环境可能对其方法的并发调 用,这样设计的对象类可适应于各种环境(顺序和并发)。因此,集成途径是从对象 模型本身的特点出发考虑对象模型的并发控制,它不仅使得设计的对象(类)便于使 用,而且还有利于对象类的重用。 2.3.1集中控制和分散控制 对象的并发控制从方式上可以分为集中控制和分散控制。集中控制是指把对 象的并发控制集中在对象(类)的某一处进行描述。例如,用主动对象的体控制消息 的接受就属于一种集中控制。另一种集中控制方式是采用一种较抽象的形式(如: 路径表达式)来描述对象的并发行为,当对象接收消息时,根据这个抽象的并发描 述决定是否处理所接收到的消息。采用集中控制方式来实现对象的并发控制要求: 在设计并发对象类时,必须对对象的并发行为有一个整体的了解并给出完整的描 11
第二章 在面向对象模型中引进并发 11 度策略设计的不好,就会出现多个read消息"合谋饿死"write消息的情形。因此,对 象在进行消息接收的调度时,应考虑调度策略的公平性。 2.3 对象的并发控制 在并发面向对象模型中,对象间不存在共享变量但存在共享对象。处于并发 环境中的对象随时都会面临环境对其方法的并发调用,如果对方法的并发调用不 进行同步控制,将会造成对象状态的混乱,从而导致整个系统行为的不正确。 如何在对象模型中进行并发控制,一般存在两种途径,即:正交途径和集成 途径。在正交途径中,系统的并发执行与对象分开考虑,对象本身不提供并发控 制,而是在对象的方法中显式地采用传统的同步机制(如:信号量等)来控制系统的 并发与同步,并发控制可以在消息发送方的方法中进行,也可以在消息接受方的 方法中完成。正交途径只是在传统并发程序设计基础上加上了对象这个框架,并 没有从面向对象模型本身的特点来考虑并发,一个对象的并发控制要依赖于其它 对象的配合,从而不符合对象所具有的自治性与局部性特点,并且,在对象的方 法中进行并发控制会使得对象类的并发属性难以继承。 集成途径把并发与对象结合起来考虑,对象本身提供并发控制,即,对象对 其方法的并发调用进行同步控制。对象在接收消息时,将根据自身的状态决定是 否处理该消息。 对象是一个高度自治的实体,它应具有自动的自我保护能力,而不应由环境 对其行为有过多的假设。在设计对象类时应考虑外部环境可能对其方法的并发调 用,这样设计的对象类可适应于各种环境(顺序和并发)。因此,集成途径是从对象 模型本身的特点出发考虑对象模型的并发控制,它不仅使得设计的对象(类)便于使 用,而且还有利于对象类的重用。 2.3.1 集中控制和分散控制 对象的并发控制从方式上可以分为集中控制和分散控制。集中控制是指把对 象的并发控制集中在对象(类)的某一处进行描述。例如,用主动对象的体控制消息 的接受就属于一种集中控制。另一种集中控制方式是采用一种较抽象的形式(如: 路径表达式)来描述对象的并发行为,当对象接收消息时,根据这个抽象的并发描 述决定是否处理所接收到的消息。采用集中控制方式来实现对象的并发控制要求: 在设计并发对象类时,必须对对象的并发行为有一个整体的了解并给出完整的描
第二章在面向对象模型中引进并发 述。 分散控制方式是把对象的并发控制描述分布到对象的各方法上,其中一种是 在对象各方法的实现中进行同步控制,对象无条件地接受消息,在消息的处理方 法中,根据对象目前的状态决定是等待还是继续执行。另一种分散控制方式是在 对象类中给每个方法定义一个执行条件,当对象接收到消息时,将根据相应方法 的执行条件来决定是否处理该消息,对不满足执行条件的消息让其等待。采用分 散控制方式进行对象的并发控制不必要求在设计并发对象类时掌握对象并发行为 的全局知识,而是针对每一个消息处理方法来考虑对象的并发控制。 2.3.2隐式控制和显式控制 对象的并发控制除了可分为集中控制和分散控制外,还可以分为隐式控制和 显式控制。隐式控制是指:在并发对象类的定义中把对象的并发限制作为对象的 属性进行描述,并不给出具体控制代码,对象的并发控制代码由编译系统根据对 象类的并发属性自动产生,对象在接受消息时隐式地调用这段代码。 在隐式控制方式中,对象的并发属性描述和功能(方法实现)描述可以放在同一 个类中,也可以用一些抽象的并发模板类来描述对象的各种并发模型,在定义 个并发对象类时,这个类本身只给出消息处理方法的实现,不考虑并发,但在类 的定义中必须指定继承哪一个并发模板类,由这并发模板类来规定所定义的并发 对象类的并发行为。 显式控制是指:在对象类的定义中明确地给出并发控制代码,这些代码可以 放在对象各方法的实现中,也可以用专门的设施(如:对象体)来实现。 隐式控制的好处在于可以把对象的并发控制与对象方法的实现分开考虑,在 定义并发对象类的子类时,可以分别继承父类的并发控制和方法的实现。隐式控 制的不足之处在于它限制了系统的表达能力,使得对象的并发控制不灵活。 显式控制的优点是使得对象的并发控制描述比较灵活,缺点是:它使得对象 的并发控制缺乏系统性,容易出错,另外,在定义并发类的子类时,如果要修改 父类的并发控制,就必须连父类方法的实现一起修改,造成不必要的方法重定义。 2.3.3对象并发状态的表示 对象是数据和操作的封装体,数据存放在对象的局部变量中,对象的状态由 对象所有局部变量在某一时刻的取值来表示。在并发环境中,还要考虑对象的并 发状态描述问题,因为,对象的并发控制是根据对象的并发状态来进行的。 12
第二章 在面向对象模型中引进并发 12 述。 分散控制方式是把对象的并发控制描述分布到对象的各方法上,其中一种是 在对象各方法的实现中进行同步控制,对象无条件地接受消息,在消息的处理方 法中,根据对象目前的状态决定是等待还是继续执行。另一种分散控制方式是在 对象类中给每个方法定义一个执行条件,当对象接收到消息时,将根据相应方法 的执行条件来决定是否处理该消息,对不满足执行条件的消息让其等待。采用分 散控制方式进行对象的并发控制不必要求在设计并发对象类时掌握对象并发行为 的全局知识,而是针对每一个消息处理方法来考虑对象的并发控制。 2.3.2 隐式控制和显式控制 对象的并发控制除了可分为集中控制和分散控制外,还可以分为隐式控制和 显式控制。隐式控制是指:在并发对象类的定义中把对象的并发限制作为对象的 属性进行描述,并不给出具体控制代码,对象的并发控制代码由编译系统根据对 象类的并发属性自动产生,对象在接受消息时隐式地调用这段代码。 在隐式控制方式中,对象的并发属性描述和功能(方法实现)描述可以放在同一 个类中,也可以用一些抽象的并发模板类来描述对象的各种并发模型,在定义一 个并发对象类时,这个类本身只给出消息处理方法的实现,不考虑并发,但在类 的定义中必须指定继承哪一个并发模板类,由这并发模板类来规定所定义的并发 对象类的并发行为。 显式控制是指:在对象类的定义中明确地给出并发控制代码,这些代码可以 放在对象各方法的实现中,也可以用专门的设施(如:对象体)来实现。 隐式控制的好处在于可以把对象的并发控制与对象方法的实现分开考虑,在 定义并发对象类的子类时,可以分别继承父类的并发控制和方法的实现。隐式控 制的不足之处在于它限制了系统的表达能力,使得对象的并发控制不灵活。 显式控制的优点是使得对象的并发控制描述比较灵活,缺点是:它使得对象 的并发控制缺乏系统性,容易出错,另外,在定义并发类的子类时,如果要修改 父类的并发控制,就必须连父类方法的实现一起修改,造成不必要的方法重定义。 2.3.3 对象并发状态的表示 对象是数据和操作的封装体,数据存放在对象的局部变量中,对象的状态由 对象所有局部变量在某一时刻的取值来表示。在并发环境中,还要考虑对象的并 发状态描述问题,因为,对象的并发控制是根据对象的并发状态来进行的
第二章在面向对象模型中引进并发 1.隐式描述 对象的并发状态往往也隐含在这些成员变量中。例如:对于一个有界缓存对 象(bounded buffer),其状态可由三个成员变量表示:buffer、in、out,存放在有界 缓存对象中的元素由buffer表示,buffer中元素的数量由in和out表示。这里,in和out 除了表示buffer中元素的个数以外,还表示了有界缓存对象的并发状态。当in=out 时,缓存为空,不能接收get消息;当(im+1)MOD max len=out时,缓存已满,不 能接收put消息。 2.显式描述 为了更加清晰地表示对象的并发状态,可把对象的并发状态和非并发状态分 开进行描述。对象的方法在对象的非并发状态上进行操作,而对象的并发控制在 对象的并发状态上进行操作。把对象的并发状态和非并发状态分开可有很多做法: (1)给对象加上一个路径表达式,用于表示对象的各种并发限制,对象接受消 息时将根据该路径表达式来决定是否处理接收到的消息35]。 (2)用单独的一组成员变量来表示对象的并发状态,这些变量只能由对象的并 发控制使用,对象的方法不能对它们进行操作]。 (3)把对象的并发状态表示为若干个由对象的方法所组成的集合,这些集合被 称为行为抽象[4],每个集合给出了对象在某一时刻所能接受的消息。例如对于上 述的有界缓存对象,其行为抽象可表示为三个集合:{get}、{put}和{get,put},其 中,{get}表示缓存满,{put}表示缓存为空,{get,put}表示缓存不空也不满。 把对象的并发状态描述从对象的非并发状态中分离出来,其好处在于对象的 并发行为容易理解,有利于对象的并发控制,并且为解决并发对象类的继承异常(详 见2.3.2)提供了一种途径。不足之处在于,它加重了程序设计者的负担,它要求程 序设计者必须在二类状态(并发与非并发)上考虑问题,处理不慎易造成二类状态间 的不一致。 2.4并发与继承 继承是面向对象技术的一个重要特性,它是一种信息共享机制,是实现软件 重用的一个重要手段。对于并发面向对象模型而言,继承更显得重要,因为并发 程序很难设计,如果能利用己有的并发程序代码来设计新的并发系统将会减轻工 作量。因此,在面向对象模型中引进并发机制的同时,应该要考虑对继承机制的 13
第二章 在面向对象模型中引进并发 13 1. 隐式描述 对象的并发状态往往也隐含在这些成员变量中。例如:对于一个有界缓存对 象(bounded buffer),其状态可由三个成员变量表示:buffer、in、out,存放在有界 缓存对象中的元素由buffer表示,buffer中元素的数量由in和out表示。这里,in和out 除了表示buffer中元素的个数以外,还表示了有界缓存对象的并发状态。当in=out 时,缓存为空,不能接收get消息;当 (in+1) MOD max_len = out时,缓存已满,不 能接收put消息。 2. 显式描述 为了更加清晰地表示对象的并发状态,可把对象的并发状态和非并发状态分 开进行描述。对象的方法在对象的非并发状态上进行操作,而对象的并发控制在 对象的并发状态上进行操作。把对象的并发状态和非并发状态分开可有很多做法: (1)给对象加上一个路径表达式,用于表示对象的各种并发限制,对象接受消 息时将根据该路径表达式来决定是否处理接收到的消息[35]。 (2)用单独的一组成员变量来表示对象的并发状态,这些变量只能由对象的并 发控制使用,对象的方法不能对它们进行操作[71]。 (3)把对象的并发状态表示为若干个由对象的方法所组成的集合,这些集合被 称为行为抽象[49],每个集合给出了对象在某一时刻所能接受的消息。例如对于上 述的有界缓存对象,其行为抽象可表示为三个集合:{get}、{put}和{get, put},其 中,{get}表示缓存满,{put}表示缓存为空,{get,put}表示缓存不空也不满。 把对象的并发状态描述从对象的非并发状态中分离出来,其好处在于对象的 并发行为容易理解,有利于对象的并发控制,并且为解决并发对象类的继承异常(详 见2.3.2)提供了一种途径。不足之处在于,它加重了程序设计者的负担,它要求程 序设计者必须在二类状态(并发与非并发)上考虑问题,处理不慎易造成二类状态间 的不一致。 2.4 并发与继承 继承是面向对象技术的一个重要特性,它是一种信息共享机制,是实现软件 重用的一个重要手段。对于并发面向对象模型而言,继承更显得重要,因为并发 程序很难设计,如果能利用已有的并发程序代码来设计新的并发系统将会减轻工 作量。因此,在面向对象模型中引进并发机制的同时,应该要考虑对继承机制的
第二章在面向对象模型中引进并发 支持,采用的并发机制应不损害面向对象模型的继承特性。 然而,很多的研究表明:在面向对象模型中,并发与继承不是两个独立的概 念,它们存在相互冲突的性质59,15,31,62,71,85]。这个问题解决的不好,将会带来继 承异常现象5列,它使得并发对象类难以继承。 由于并发与继承间存在冲突,不少的并发面向对象模型放弃了把继承作为它 们的主要语言特性,即使存在支持继承的并发对象模型,但它们对继承的支持程 度也是不一样的,这主要取决于它们采用何种并发控制机制。 2.4.1同步限制、同步代码与同步机制 在并发环境中,处于某状态下的对象不是对发送给它的所有消息都能处理, 它必须要根据目前的(并发)状态决定能处理哪些消息,即对象在接收消息处理时必 须要满足某种限制,这种限制被称为对象的同步限制(synchronization constraint)。 例如对于有界缓存对象,其并发限制是:当缓存为空时只能接收put消息,不能接 收get消息;当缓存满时只能接收get消息不能接收put消息。 在对象中为了实现同步限制,必须提供相应的并发控制代码,即同步代码 (synchronization code),这个同步代码必须要与对象的同步限制相一致,否则对象 的语义将发生错误。 如何实现对象的同步代码,采用集中控制还是分散控制、隐式控制还是显式 控制,实现同步代码的方式被称为对象的同步机制(synchronization scheme): 2.4.2继承异常 一个并发对象包括两方面的操作:并发控制和消息处理。在定义并发对象类 的子类时,不仅可以继承父类的消息处理方法,而且也应该可以继承父类的并发 控制。因为并发控制和消息处理属于对象的两类不同操作,因此在定义子类时应 对这两类操作分开进行继承。这样不仅使得并发对象类的描述比较清晰,而且还 可以在定义一个并发对象类时从现有的一些非并发对象类中继承消息处理方法, 然后再加上一些并发控制,从而可以提高软件重用范围。 然而,如果引进的并发控制机制不恰当,将会损害面向对象模型的继承机制。 例如,如果把对象的并发控制放在对象的方法中实现,那么,当定义子类时,由 于定义了新的方法而产生新的并发限制,从而需要修改父类的并发控制,这样就 要对父类的消息处理方法进行重定义,这种重定义有时是很严重的,往往需要对 父类的每个消息处理方法都要进行,这样就彻底违背了继承机制的目的,使得通 14
第二章 在面向对象模型中引进并发 14 支持,采用的并发机制应不损害面向对象模型的继承特性。 然而,很多的研究表明:在面向对象模型中,并发与继承不是两个独立的概 念,它们存在相互冲突的性质[59,15,31,62,71,85]。这个问题解决的不好,将会带来继 承异常现象[59],它使得并发对象类难以继承。 由于并发与继承间存在冲突,不少的并发面向对象模型放弃了把继承作为它 们的主要语言特性,即使存在支持继承的并发对象模型,但它们对继承的支持程 度也是不一样的,这主要取决于它们采用何种并发控制机制。 2.4.1 同步限制、同步代码与同步机制 在并发环境中,处于某状态下的对象不是对发送给它的所有消息都能处理, 它必须要根据目前的(并发)状态决定能处理哪些消息,即对象在接收消息处理时必 须要满足某种限制,这种限制被称为对象的同步限制(synchronization constraint)。 例如对于有界缓存对象,其并发限制是:当缓存为空时只能接收put消息,不能接 收get消息;当缓存满时只能接收get消息不能接收put消息。 在对象中为了实现同步限制,必须提供相应的并发控制代码,即同步代码 (synchronization code),这个同步代码必须要与对象的同步限制相一致,否则对象 的语义将发生错误。 如何实现对象的同步代码,采用集中控制还是分散控制、隐式控制还是显式 控制,实现同步代码的方式被称为对象的同步机制(synchronization scheme)。 2.4.2 继承异常 一个并发对象包括两方面的操作:并发控制和消息处理。在定义并发对象类 的子类时,不仅可以继承父类的消息处理方法,而且也应该可以继承父类的并发 控制。因为并发控制和消息处理属于对象的两类不同操作,因此在定义子类时应 对这两类操作分开进行继承。这样不仅使得并发对象类的描述比较清晰,而且还 可以在定义一个并发对象类时从现有的一些非并发对象类中继承消息处理方法, 然后再加上一些并发控制,从而可以提高软件重用范围。 然而,如果引进的并发控制机制不恰当,将会损害面向对象模型的继承机制。 例如,如果把对象的并发控制放在对象的方法中实现,那么,当定义子类时,由 于定义了新的方法而产生新的并发限制,从而需要修改父类的并发控制,这样就 要对父类的消息处理方法进行重定义,这种重定义有时是很严重的,往往需要对 父类的每个消息处理方法都要进行,这样就彻底违背了继承机制的目的,使得通
第二章在面向对象模型中引进并发 过继承进行软件重用的机制大打折扣。上述现象在5]中被称为继承异常。 关于继承异常的研究普遍认为,造成继承异常的原因主要在于所采用的同步 机制,并且不同的同步机制所造成继承异常的程度又各不相同。解决继承异常的 关键在于,应该把对象的并发控制代码与对象的功能性代码(对象的方法)分开进行 设计。 2.5对象与进程 在面向对象模型中引进并发,不可避免地要涉及到进程,因为进程是目前进 行并发程序设计的主要概念。在一些并发面向对象的研究中,首先考虑的是采用 何种面向对象成分描述进程。目前,在面向对象模型中描述进程的典型做法是引 进主动对象的概念,用主动对象描述进程,用对象体描述进程的执行。 虽然对象与采用消息传递机制进行通信的进程有很多相似之处,例如:它们 都有状态,都能接收消息,但是,进程与对象是有本质区别的。首先,进程是一 个实现级的概念,而面向对象软件模型是为了对客观世界中的活动进行自然模拟, 其中的对象对应着一些有形或无形的实在对象,如果在其中混入一些实现方面的 具体内容,将会影响模型描述问题的清晰度。其次,进程有自己固定的执行次序, 即,先做什么,再做什么;何时接收消息,何时发送消息,等等,都已在进程中 明确规定了,即使在进程中引进了不确定性成分,如:选择式通信语句及卫士命 令43]等,但其总体执行行为己经确定。而对象的执行行为是由对象的使用者决定。 一般来说,对象向外提供很多服务,何时及采用什么次序来使用这些服务是由使 用者根据需要决定,而不应该由对象对其使用者的行为有过多的限制,当对象处 于不适合于提供某种服务的状态时,可以让使用者等待。如果用主动对象来描述 进程,这样就规定了对象的执行行为,同时也限制了使用者使用该对象的方式。 最后,在对象体中实现对象的并发控制将会带来继承异常。 2.6现有系统介绍 目前,关于并发面向对象模型的研究有很多,为了对这些研究有一个整体的 了解,以及考察它们对上述问题的解决方案,从中获得启发,本节选择一些典型 的并发面向对象系统进行介绍。 15
第二章 在面向对象模型中引进并发 15 过继承进行软件重用的机制大打折扣。上述现象在[59]中被称为继承异常。 关于继承异常的研究普遍认为,造成继承异常的原因主要在于所采用的同步 机制,并且不同的同步机制所造成继承异常的程度又各不相同。解决继承异常的 关键在于,应该把对象的并发控制代码与对象的功能性代码(对象的方法)分开进行 设计。 2.5 对象与进程 在面向对象模型中引进并发,不可避免地要涉及到进程,因为进程是目前进 行并发程序设计的主要概念。在一些并发面向对象的研究中,首先考虑的是采用 何种面向对象成分描述进程。目前,在面向对象模型中描述进程的典型做法是引 进主动对象的概念,用主动对象描述进程,用对象体描述进程的执行。 虽然对象与采用消息传递机制进行通信的进程有很多相似之处,例如:它们 都有状态,都能接收消息,但是,进程与对象是有本质区别的。首先,进程是一 个实现级的概念,而面向对象软件模型是为了对客观世界中的活动进行自然模拟, 其中的对象对应着一些有形或无形的实在对象,如果在其中混入一些实现方面的 具体内容,将会影响模型描述问题的清晰度。其次,进程有自己固定的执行次序, 即,先做什么,再做什么;何时接收消息,何时发送消息,等等,都已在进程中 明确规定了,即使在进程中引进了不确定性成分,如:选择式通信语句及卫士命 令[43]等,但其总体执行行为已经确定。而对象的执行行为是由对象的使用者决定。 一般来说,对象向外提供很多服务,何时及采用什么次序来使用这些服务是由使 用者根据需要决定,而不应该由对象对其使用者的行为有过多的限制,当对象处 于不适合于提供某种服务的状态时,可以让使用者等待。如果用主动对象来描述 进程,这样就规定了对象的执行行为,同时也限制了使用者使用该对象的方式。 最后,在对象体中实现对象的并发控制将会带来继承异常。 2.6 现有系统介绍 目前,关于并发面向对象模型的研究有很多,为了对这些研究有一个整体的 了解,以及考察它们对上述问题的解决方案,从中获得启发,本节选择一些典型 的并发面向对象系统进行介绍