用于受控运行时环境的利用锁膨胀进行线程同步的方法和装置的制作方法

文档序号:6655917阅读:154来源:国知局
专利名称:用于受控运行时环境的利用锁膨胀进行线程同步的方法和装置的制作方法
技术领域
本公开总体涉及计算机,更具体而言,涉及用于受控运行时环境的利用锁膨胀(lock inflation)进行线程同步的方法和装置。
背景技术
支持多线程应用的软件环境,例如,JAVA和欧洲计算机制造商协会(ECMA)通用语言架构(CLI),通常包括用于在一个或多个线程都可以访问对象时进行协调的同步机制。正如本领域普通技术人员所理解的那样,线程指被组织成单个执行控制流以处理一个或多个对象的一系列处理器指令。对象是类的实例,其中,类是数据和对这样的数据进行操作的方法的集合。在执行多线程的情形中,一定要注意避免多个线程同时对同一个对象进行修改从而使得该对象可能处于错误状态。特别是,线程可具有临界区,该临界区对有可能同时被另一线程访问的对象进行操作。从而,多线程系统通常提供专门的声明,以免线程临界区的操作在临界区执行期间被访问该共享对象的一个或多个其他线程破坏。
例如,JAVA源代码可包括synchronized(同步)声明,以免对象同时被不同线程所访问。使用该synchronized声明能够获取由该synchronized声明所标识出的对象的排他锁。从而,可防止线程执行代码的临界区,直至该线程能够获得由synchronized声明所标识的特定对象上的排他锁为止。此外,一旦获得这样的锁,任何其他线程都不能访问被锁定的对象,从而防止在执行代码的临界区期间因正在执行的处理所带来的无意的破坏。这样的锁定过程可用于确保多个线程不会以导致在同一时间代码的临界区的执行发生冲突的方式对共享对象进行访问。当然,synchronized声明的应用通常用于如下情形,即,特定程序创建多个线程来共享对象和/或方法。如果任何时候都仅有一个线程访问特定对象和/或方法,则无需通过synchronized声明对其进行保护。
在JAVA源代码中的synchronized声明通常被转换成JAVA虚拟机(JVM)指令,这是因为,如本领域所公知的那样,在JAVA源代码被JVM执行前,首先将其编译成字节码(即,JVM语言)。例如,可将synchronized声明转换成monitorenter(监视器进入)JVM指令,以得到/获得对象上的排他锁。与monitorenter指令相呼应,还提供monitorexit(监视器退出)JVM指令,用于解锁/释放对象上的排他锁。因此,如果线程对对象成功地执行了monitorenter指令,则该线程得到该对象的临时排他锁拥有权(即,它已经获得了该对象上的锁,以避免其他线程访问该代码的临界区)。如果当第一线程具有对象的临时排他锁拥有权时,另一线程,或第二线程试图对同一对象执行monitorenter指令,则第二线程必须等待(例如,休眠或旋转(spin)),直至第一线程(即,当前锁拥有者)执行monitorexit指令而释放其对于该对象的排他锁为止。
通常使用两个状态变量来描述对象的锁状态。第一状态变量为锁拥有者,其与当前拥有该锁的线程的线程标识符相对应。对于锁未被任何线程所拥有的情形,可将锁拥有者设置为NULL(空)值或NULL线程。第二状态变量为锁递归计数器,其可用于指示锁拥有者已经获取该锁的次数(以支持递归锁定)。一般而言,将对象的锁状态初始化为锁拥有者等于NULL值(相当于未锁定状态)和锁递归计数器等于零。
通常来讲,锁定字(lockword)用于表示对象的锁状态。Bacon等人在“Thin LockFeatherweight Synchronization for JAVA”(Conference on Programming Languages Design andImplementation,1998年,第258-268页)中定义出一种用于对象锁定/同步的通用技术。Bacon等人定义的基于锁定字的技术中,锁定字可具有两种形式,即,瘦形和胖(inflated)形。瘦锁可仅包括线程标识符和锁递归计数器状态变量,由于其尺寸相对较小,可将其存储在对象的头部(header)内。胖锁可包括多个附加数据结构,以便支持在对于其中瘦锁不足以胜任的情形中(例如,在锁竞争的情形中,可能需要等待获取该对象锁的线程的列表)的对象锁定/同步。一般而言,将对象初始化成具有瘦锁。然后,例如当锁变得太大以至于不适于放在对象头部中时(例如,如果存在锁竞争以及需要等待线程的列表,如果锁递归计数器超过瘦锁可表示的最大值,等等),锁定/同步过程将使得该锁膨胀。在大多数实现方式中,锁定/同步过程不会将胖锁收缩回瘦锁(即,一旦将对象锁转换成胖锁,对于程序执行的其余部分,它将保持为胖锁)。
在许多现有对象锁定技术(例如,JVM monitorenter和monitorexit指令的现有实现方式)中,锁释放功能(例如,相当于monitorexit指令)确定试图释放该锁的线程实际上是否为该锁的锁拥有者。另外,锁释放功能检查锁递归计数器,以确定是应将该锁解锁还是保持原样(例如,由于多个递归锁获取而保持在锁定状态中)。然而,使用高级语言(例如,JAVA)编写的、随后编译成字节码的大多数格式良好的应用程序都包括锁获取和释放操作的匹配对(例如,monitorenter和monitorexit JVM指令的匹配对),因此,表现出平衡的同步特性(即,包括通过同一线程执行的平衡的锁获取和释放对的锁定序列)。在表现出平衡的同步特性的代码中,用于检查锁拥有者和锁递归计数器状态变量的额外开销可能不是必需的,因此,这可能降低执行应用程序的整体效率。


图1的框图表示其中可采用此处所述示例性的方法、装置和制品的示例性受控运行时环境;图2的框图表示可用于图1的受控运行时环境中的示例性锁管理器;图3A表示可由示例性的现有锁管理器采用的用于图1的受控运行时环境中的示例性锁定字;图3B表示可由图2的示例性锁管理器采用的示例性锁定字;
图4A-4B的流程图表示,可由机器执行以实现可用于图1的受控运行时环境中的示例性现有锁管理器的示例性机器可读指令;图5的流程图表示可由机器执行以实现图2的示例性锁管理器的示例性机器可读指令;图6的流程图表示可由机器执行以实现图2的示例性乐观平衡锁同步单元的示例性机器可读指令;图7的流程图表示可由机器执行以实现图2的示例性不平衡锁获取单元的示例性机器可读指令;图8的流程图表示可由机器执行以实现图2的示例性不平衡锁释放单元的示例性机器可读指令;图9的流程图表示可由机器执行以修改未决平衡释放的状态以便由图6和7所示处理使用的示例性机器可读指令;图10A-10C表示图2的锁管理器的示例性操作;以及图11表示可执行如图4-9所示处理以实现图2的锁管理器的示例性处理器系统。
具体实施例方式
图1示出了可使用此处所述示例性方法、装置和制品的示例性使用环境100的框图。示例性使用环境100可通过例如一个或多个处理器系统(例如,以下所述的图11中的示例性处理器系统1100)来实现。尽管图1所示的示例相当于基于JAVA的受控运行时环境(MRTE),本领域普通技术人员应该理解,可将此处所述示例性的方法、装置和制品应用到任何类似的MRTE使用环境中,例如,CLI和相关的C#语言。
示例性使用环境100包括在图1中表示为JAVA虚拟机(JVM)110的MRTE。示例性JVM110动态地将由机器无关指令或字节码114所表示的程序转换成机器相关的或本机的指令,然后在一个或多个处理器120(例如,以下所述的处理器1112)上执行该本机指令。JVM 110可通过对于一个或多个处理器120专用的操作系统(OS)130(例如,Microsoft Windows OS,UNIX OS,Linux OS等)执行该本机指令。
在图1的示例中,JVM110对存储在多个类文件114中的字节码114进行处理。一般而言,类文件114存储与单个JAVA类相对应的字节码114,该字节代码包括用于定义该类的接口、字段和方法。JAVA编译器134可根据由例如软件开发者编写的JAVA程序源代码创建类文件114。JAVA编译器134、相关的JAVA源代码138和最终类文件114(或字节码114)在本领域中是公知的,在此不再对其进行更多描述。
为了对类文件114进行处理,示例性的JVM110包括类加载器142,其用于定位与一个或多个专用类相对应的一个或多个专用类文件114,以便通过将所加载的类文件114的本地映像存储到本地存储器146中,而将这样的类文件114加载到JVM110的执行引擎144。在将所加载的类文件114存储到存储器146之前,类加载器142可调用字节码检验器150,以检验所加载的类文件114的结构是否正确,以及是否符合JAVA语言的结构。然后,在上述两者中任一的情形中,JVM110的执行引擎144使用例如解释器154和/或一个或多个即时(JIT)编译器158,将所加载的机器无关的字节码转换成机器相关指令。
解释器154将字节码114转换成用于在目标处理器120上实现字节码114的功能的一组机器相关指令。换而言之,解释器154提供仿真层,以允许字节码114在目标处理器120上执行,就好像处理器120直接支持JAVA指令集。另一方面,JIT编译器158将一组字节码114编译成用于在目标处理器120上执行的一组机器相关指令。单个字节码114的具体功能可能不会准确地被转换成机器相关指令,但是最终得到的一组机器相关指令的总体功能将等效于原始的一组字节码114。从而,JIT编译器158可比解释器154产生出更优的代码。然而,解释器154可比JIT编译器158更容易实现。
为执行解释器154和/或一个或多个JIT编译器158提供的程序代码,JVM110的执行引擎144可在本地存储器146中定义一个或多个存储区。例如,为支持多个线程的同时执行,JVM110可为存储器146中的每个线程分配独立的虚拟程序计数器(pc)寄存器和独立的JVM堆栈帧。JVM堆栈帧可用于存储例如对应于相关执行线程的局部变量和部分结果。此外,JVM110可定义在本地存储器146中对所有线程共用的存储区。例如,这样的存储区可包括用于存储在程序执行期间创建的对象的堆、用于存储例如用于实现特定类的方法的数据和代码的方法区,和用于存储与特定类相关的常量的运行时常量池。为了有效管理存储器146的运行时部分,JVM110可包括例如用于自动对堆中对象进行解除分配以便为随后程序执行而腾空存储器的垃圾收集器162。
为了支持多线程的同时执行,JVM110的执行引擎144包括线程支持模块166。线程支持模块166支持通过创建线程对象的线程的创建,以及通过调用线程的启动方法的线程执行。此外,线程支持模块166可通过使用多个优先级别来支持对线程的优先执行。在本发明中特别值得注意的是,JVM110的执行引擎144还包括锁管理器170,其用于解决当两个或多个线程试图访问同一共享对象时可能发生的冲突。
对应于示例性JVM110的工业标准规范(以及用于其他受控运行时环境的规范)定义了用于支持多线程之间对象同步的过程。JVM110为每个对象提供同步锁。线程可通过获得与对象相关的锁的拥有权来获得该对象的拥有权。同样,线程可通过释放与该对象相关的锁的拥有权来释放该对象的拥有权。在JAVA编程语言中,通过synchronized声明来实现对象和方法的同步。JVM110的规范定义了分别通过monitorenter和monitorexit字节码来实现锁获取和释放操作。然而,并没有定义出monitorenter和monitorexit字节码的实现。
图2示出了可用于实现如图1所示的示例性锁管理器170的示例性锁管理器200的框图。示例性锁管理器200基于大多数锁获取和锁释放将是平衡的或乐观(optimistically)平衡的假设而获取和释放对于一个线程的对象的锁。例如,如果对于锁的一组获取和释放操作出现在同一嵌套级,以及处在这样的操作之间的代码的临界区不包含同步操作,或仅包含对该锁的其他平衡同步操作(例如,线程获取对象的锁,执行程序代码的临界区,然后释放该对象的锁),则锁管理器200可确定该组获取和释放操作是平衡的。同样,如果对锁的一组获取和释放操作出现在同一嵌套级,但锁管理器200不能十分确定所有操作是平衡的(例如,在代码的临界区包含方法调用的情形中),则锁管理器200确定该组获取和释放操作是乐观平衡的。使用高级语言(例如,JAVA)编写的、然后编译成字节码(例如,字节码114)的多数格式良好的程序表现出平衡的同步特性(即,包含如前所述平衡的获取和释放对的同步)。然而,在很少情形中,锁获取或释放可能是不平衡的(例如,可能是使用人工编写的字节码实现程序的情形)。因此,除平衡和乐观平衡锁处理过程外,锁管理器200可采用不平衡的获取和释放过程分别获取和释放对象的锁。
如图2所示,锁管理器200包括锁同步控制器204,锁同步控制器204从正在执行的线程接受对象标识符输入208和线程上下文输入212。对象标识符输入208用于标识将要同步的对象,并可包括惟一的对象实例标识符、对象的锁定字等。线程上下文输入212用来指示寻求对由对象标识符输入208所标识的对象进行锁定或解锁的线程的身份、该线程的操作状态和用于对该对象的锁执行的相关操作(例如,用于获取锁或释放锁,获取和/或释放为平衡的、乐观平衡的还是不平衡的)。锁同步控制器204提供对象锁状态输出216,以指示对象的锁的状态(例如,初次获得、递归获得、释放/解锁、抛出异常等)。
另外,锁同步控制器204基于将要对由对象标识符输入208所标识的对象的锁进行的锁定操作的类型,调用特定的锁定操作单元。示例性类型的锁定操作包括乐观平衡锁同步(对应于对象锁的平衡的同步或乐观平衡的同步)、不平衡锁获取和不平衡锁释放。锁同步控制器204可基于通过线程上下文输入212提供的信息确定锁定操作的类型。该信息可例如通过图1所示的解释器154和/或JIT编译器158确定,作为从字节码114到由线程上下文输入212所标识的线程执行的机器相关指令集的转换的一部分。
为了执行对象的平衡锁同步(或在对象的乐观平衡同步的情形中试图执行平衡同步),示例性的锁管理器200包括乐观平衡锁同步单元220。如果锁同步控制器204确定应对对象执行平衡(或乐观平衡)同步(例如,基于对象标识符输入208和线程上下文输入212),则乐观平衡锁同步单元220可确定与对象相关的锁的当前形式是否支持乐观平衡同步。例如,仅当相关的对象锁处在瘦模式中时,可将乐观平衡同步单元220配置成执行对象的乐观平衡同步。相反,如果锁处在胖模式中(例如,由于对象锁的先前竞争,先前对锁执行的不平衡锁定操作等),乐观平衡锁同步单元220可被配置成回退到已知的锁定技术(例如,以上所述由Bacon等人描述的技术)。
例如,如果瘦锁与要锁定的对象相关,则乐观平衡同步单元220确定是否已有线程获取了该对象的锁。如果预期对象的锁可用(或已被请求线程拥有),则乐观平衡锁同步单元220存储该锁的当前状态,并获取该线程的锁。如果该锁不可用,或例如,胖锁与该对象相关,则乐观平衡锁同步单元220调用已知的锁膨胀/竞争过程,以便在该锁变得可用之后为该线程获得该锁。在以上两种情形任意之一中,乐观平衡锁同步单元220然后可使得锁同步控制器204更新锁状态输出216,以指示已获取该对象锁。
线程执行完要求锁定对象的代码(例如,如线程上下文输入212所指示的)之后,可向乐观平衡锁同步单元220发送信号,以便如果瘦锁仍与该对象相关联,则通过将锁恢复到其先前状态来释放该对象的锁,或者在胖锁的情形中,通过执行已知的胖锁释放过程来释放该对象的锁。释放了该对象锁之后,乐观平衡同步单元220可导致/发送信号至锁同步控制器204来相应地更新对象锁状态输出216。为了支持由单个线程进行的递归锁获取,乐观平衡锁同步单元220包括同步映射,以便跟踪与给定对象的所有乐观平衡同步相对应的所有活动乐观平衡锁获取的状态。同步映射可用于代替锁递归计数器来跟踪线程已获取特定对象的次数。
为了执行不平衡锁获取或不平衡锁释放,锁管理器200分别包括不平衡锁获取单元224和不平衡锁释放单元228。如果锁同步控制器204确定应对对象执行不平衡锁获取(例如,基于线程上下文输入212),那么,若该锁可用(或已被该线程所拥有),不平衡锁获取单元224获取用于该线程的对象的锁,或者,若锁不可用,则调用已知的锁竞争过程。如果锁同步控制器204确定应对对象执行不平衡释放,那么,如果该对象的锁当前被该线程所拥有,则不平衡锁释放单元228释放/解锁该锁。如果该锁不为该线程所拥有,那么不平衡锁释放单元228抛出异常以指示试图进行无效的锁释放。从而,根据是执行锁获取还是锁释放,不平衡锁获取单元224或不平衡锁释放单元228分别可使得锁同步控制器204更新锁状态输出216,以指示对象锁的正确状态。另外,如果瘦锁当前与该对象相关,则不平衡锁获取单元224或不平衡锁释放单元228可分别使得该对象锁膨胀。
不平衡锁获取单元224和不平衡锁释放单元228可能需要修改由乐观平衡锁同步单元220所存储的活动乐观平衡锁获取状态的同步映射。例如,不平衡锁获取或不平衡锁释放可能需要将对象锁从瘦锁膨胀到胖锁。为执行该锁膨胀,可基于在同步映射中的表项确定锁递归计数器状态变量。另外,对于在同步映射中的每个未决平衡释放,可能需要修改锁形式标志。从而,为了更新乐观平衡锁同步单元220所保持的同步映射,示例性锁管理器200包括平衡同步状态跟踪器/修改器236。平衡同步状态跟踪器/修改器236可用于确定与特定对象相对应的活动乐观平衡获取的数量,以及用于修改与特定的活动乐观平衡锁获取相对应的锁形式。不平衡锁获取单元224或不平衡锁释放单元228可根据正在执行的锁操作(即,分别为不平衡获取或平衡释放),调用平衡同步状态跟踪器/修改器236。
图3A示出可由图1的锁管理器170的现有实现使用的示例性锁定字的格式。相对照地,图3B示出可由例如图1的锁管理器170和/或锁管理器200的所披露的实现使用的示例性锁定字的格式。参看图3A,该图示出支持瘦和胖锁的示例性的现有锁定字格式。示例性的现有锁定字格式300具有32位,支持瘦和胖锁。锁定字的形式(例如,瘦还是胖)由1位的锁形式304表示。例如,0值可表示瘦锁,而有值或1值可表示胖锁。对于瘦锁(例如,锁形式304等于0),锁定字格式300包括15位的锁拥有者标识符(ID)308和8位的递归计数312。锁形式位304和锁拥有者ID308合在一起表示锁拥有者字段316。其余8位的其他字段320可以例如用于存储其他的对象相关信息,例如,对象哈希代码,用于垃圾收集器162的标志等。
对于胖锁(例如,锁形式304等于1),锁定字格式300包括23位的监视器ID324。例如,监视器ID324可存储胖锁高速缓存索引,该索引指向与对象锁相对应的、存储在胖锁高速缓存中的一组数据结构。如前所述,诸如由Bacon等人所述的现有对象锁定/同步技术,在瘦锁变得过大以至于不适合瘦锁格式时,可使得瘦锁膨胀。这可能会发生在例如当出现锁竞争时且等待该锁的一列线程需与该对象相关联(例如,单个锁拥有者ID308不够)的情况下,递归计数溢出(例如,不适合于8位的递归计数字段312)的情况下,等等。
参看图3B,该图示出了具有16位(图3A的示例性的现有锁定字格式所需位数的三分之二)且支持瘦和胖锁的示例性的披露的锁定字格式350。锁定字的形式(例如,瘦或胖)由1位的锁形式354表示。例如,0值可表示瘦锁,而有值或1值可表示胖锁。对于瘦锁(例如,锁形式354等于0),锁定字格式350包括15位的锁拥有者标识符(ID)358。锁形式位354和锁拥有者ID358合在一起表示锁拥有者字段362。与示例性的现有锁定字格式300相对照,示例性的披露的锁定字格式350不包括递归计数,这是因为,如先前所述,对对象执行的锁获取的数量可通过同步映射进行隐式跟踪。
对于胖锁(例如,锁形式354等于1),锁定字格式350包括15位的监视器ID366。至于在示例性的现有锁定字格式300中的监视器ID324,监视器ID324可存储胖锁高速缓存索引,该索引指向与对象锁相对应的、且存储在胖锁高速缓存中的一组数据结构。如先前结合以上图2所述,当对该对象的锁执行不平衡锁定操作时,该示例性的披露的锁定技术(例如,示例性的锁管理器200)可将瘦锁膨胀。例如,不平衡锁获取或不平衡锁释放可导致将瘦锁转换成胖锁。
图4A-4B示出表示用于实现图1的锁管理器170的已知的机器可读指令的流程图。图5-9示出表示用于实现图1的锁管理器170和/或图2的锁管理器200的示例性的披露的机器可读指令的流程图。在图5-9的示例中,每个流程图所表示的处理过程可通过一组机器可读指令来实现,该组机器可读指令可以包含由微处理器(例如,以下结合图11所述的示例性计算机1100中所示的处理器1112)执行的一个或多个程序。所述一个或多个程序可包含在存储在有形介质(如,CD-ROM、软盘、硬盘驱动器、DVD、或与处理器1112相关的存储器)上的软件中。然而,本领域普通技术人员应该易于理解,全部程序和/或其部分也可由除处理器1112之外的设备执行,和/或按照公知的方式包含在固件或专用硬件中。例如,锁管理器170和/或锁管理器200可通过软件、硬件,和/或固件实现。此外,尽管参照图5-9所示流程图描述了示例性程序,本领域普通技术人员应该易于想到,也可替换地使用实现此处所述示例性方法和装置的许多其他方法。例如,参照图5-9所示的流程图,可改变方框的执行顺序,和/或可将某些所述方框改变、去除、组合和/或划分成多个方框。
为了更好地理解图2的示例性锁管理器200的特性和特征,以及更好地理解以下如图5-9的流程图所示的各种处理操作,在图4A-4B中显示出用于实现图1的锁管理器170的示例性的现有处理。具体而言,图4A表示出用于获取对象的锁的示例性现有处理400,图4B表示出用于释放该对象的锁的示例性现有处理450。尽管未示出,但可使用一控制处理来基于执行的程序线程的状态确定应调用锁获取过程还是锁释放过程。
参照图4A,示例性的现有锁获取处理400开始于将与待锁定对象相关联的锁的先前锁拥有者相对应的变量/寄存器设置成等于用于表示该锁的锁定字中的瘦锁拥有者字段(例如,图3A的瘦锁拥有者字段316)的目前值(方框402)。然后,处理400通过首先确定任何线程是否己拥有该待锁定对象的锁和/或胖锁是否与该对象相关联(即,是否将瘦锁拥有者字段316设置成NULL值),而试图锁定当前线程(即,请求该锁的线程)的对象(方框404)。如果处理400确定不存在任何线程拥有者,以及瘦锁与该对象相关联(即,瘦锁拥有者字段316为NULL值)(方框404),以及由此该对象的锁己被解锁,那么,处理400通过将锁拥有者ID(如锁拥有者ID308)设置成表示该线程的值(例如,惟一的线程标识符值),而获取该线程的锁(方框408)。然而,如果处理400确定锁拥有者已存在或者胖锁与该对象相关联(即,瘦锁拥有者字段316并非为NULL值)(方框404),则处理400保持锁拥有者ID308不变。在第一线程己处在成为锁拥有者的期间,为防止第二线程试图获取该锁,通常使用单个原子操作(例如,在属于英特尔安腾处理器家族的处理器上的cmpxchg指令)实现方框402,404和408。原子操作使线程(和/或在多处理器系统中的处理器)在原子操作的执行期间对共享存储器进行排他性访问。从而,没有任何其他线程能够在原子操作执行期间修改由该原子操作所访问的存储单元。
在确定瘦锁拥有者字段316为非NULL(方框404)或锁拥有者ID308被定义成当前线程之后(方框408),处理400确定该对象的先前锁拥有者是否为NULL值(与方框408处当前线程已获得锁的情形相对应)(方框412)。如果先前锁拥有者为NULL值(方框412),则示例性处理400结束。然而,如果处理400确定先前锁拥有者并非为NULL值(方框412),则该处理确定先前锁拥有者是否为当前线程(对应于当前线程先前已获得过该对象的瘦锁的情形)(方框414)。如果先前锁拥有者为当前线程(方框414),则处理400例如可将与该锁相关联的锁递归计数器加一,以指示当前线程已多次获得该对象的瘦锁(方框416)。然后,示例性处理400结束。
然而,如果处理400确定先前锁拥有者并非为当前线程(方框414),且由此另一线程已拥有该对象的瘦锁或者胖锁已与该对象相关联,那么,处理400调用已知的锁膨胀/竞争过程,以允许当前线程在目前锁拥有者(若有的话)释放该锁之后获取该对象的胖锁(方框420)。例如,处理400可使得当前线程在执行循环中旋转或暂停执行,直至目前锁拥有者(如果有的话)释放/解锁该对象的锁为止。当该对象的锁变得可用之后,处理400则可为当前线程而膨胀和获取该锁,然后,示例性处理400结束。
参看图4B,示例性的现有锁释放处理450开始于通过首先确定与对象相关联的锁的形式,而试图释放当前线程(即,请求释放的线程)的对象(方框452)。如果胖锁与该对象相关联(例如,基于图3A的锁形式位304),则处理450调用已知的胖锁释放过程来释放该对象的胖锁(方框454)。然后,示例性处理450结束。然而,如果瘦锁与该对象相关联(方框452),则处理450确定与该对象相关联的瘦锁的锁拥有者ID(例如,锁拥有者ID308)是否与当前线程相对应(方框456)。如果锁拥有者ID308不是当前线程,且由此另一线程目前拥有该锁(方框456),则处理450抛出异常(方框458)。在方框458处,处理450可使用任何已知的异常处理技术抛出异常以指示执行了无效的释放尝试(由于不拥有该锁的线程试图对相关联的对象解锁)。然后,示例性处理450结束。
然而,如果锁拥有者ID308是当前线程(方框456),则处理450确定与该锁相关联的锁递归计数器(例如,递归计数312)是否等于零(或等效而言,指示该锁仅具有一个当前活动的获取)(方框462)。如果锁递归计数312等于零(方框462),则处理450例如通过将锁拥有者ID308设置成NULL值将该对象的锁解锁(方框466)。然而,如果锁递归计数312不等于零(方框462),则处理450将锁递归计数312减一(例如,以指示与一个活动的锁获取相对的目前的锁释放)(方框470)。在方框466或470处的处理完成后,示例性处理450随即结束。
基于由图4A-4B的示例性的现有处理400和450所提供的理解,图5示出了可用于实现图2的示例性锁管理器200的示例性锁管理器处理500。当一个或多个线程对同步对象进行操作时,可在该一个或多个线程的不同执行阶段期间调用示例性锁管理器处理500。例如,可调用示例性处理500以获取或释放对象的锁。
示例性锁管理器处理500开始于确定当前线程对该对象的锁要执行哪种类型的锁定操作(方框504)。有效的锁定操作可包括乐观平衡锁同步(包括乐观平衡锁获取和释放对)、不平衡锁获取和不平衡锁释放。例如,JIT编译器,诸如图1的JIT编译器158,可使用控制流图表和/或数据流分析来确定在程序执行期间的适当点处对对象的锁执行的锁定操作的类型。然后,JIT编译器158可输出可被锁管理器200或锁管理器处理500使用的编译代码,以便在方框504处做出正确的锁操作确定。示例性处理500可采用用于确定锁定操作是平衡的(或至少乐观平衡的)还是不平衡的任何已知技术,从而,在此不再进一步描述这些技术。
基于在方框504做出的锁定过程确定,控制继而进行到方框508、512和516的其中之一。在方框508处,锁管理器200对该对象的锁执行乐观平衡同步操作。在方框512处,锁管理器200对该对象的锁执行不平衡锁获取操作。在步骤516处,锁管理器200对该对象的锁执行不平衡锁释放操作。后面将提供分别通过图6、7和8的说明而更详细地描述的在方框508、512和516处执行的处理。
方框508、512和516处的处理完成之后,处理500确定是否至少一个锁定对象仍处未决状态,而将在将来的线程执行点处需要随后的释放(方框520)。如果有任何锁定对象处在未决状态(方框520),则控制返回到方框504及其随后方框,以允许对这样对象的锁进行处理(以及对任何附加对象的锁进行锁定)。然而,如果没有任何锁定对象处在未决状态(方框520),则处理500确定是否有要锁定的任何附加对象(方框524)。如果有要锁定的附加对象(方框524),则控制返回到方框504及其随后方框,以允许对这样对象的锁进行处理。然而,如果没有要锁定的附加对象(方框524),则示例性处理500结束。本领域普通技术人员应该理解,可通过例如对于程序(或程序的任何线程)是否仍在执行作出显式或隐式的确定,来替换在方框520和/或524处执行的条件操作。如果程序500仍在执行,则控制将返回到方框504及随后的方框508、512和516。这样的循环一直重复到处理500(或所有线程执行)结束。
图6示出可用于执行在图5的方框508处的处理和/或实现图2的乐观平衡锁同步单元220的示例性乐观平衡锁同步处理600。示例性乐观平衡锁同步处理600开始于将胖锁标志初始化为FALSE(假)(方框602)。胖锁标志用于表示与该锁相关的锁的当前形式(例如,瘦或胖)。接着,处理600将与该锁的先前锁拥有者相对应的变量/寄存器设置成等于与该对象的锁相关联的瘦锁拥有者字段(例如,图3B的瘦锁拥有者字段362)的目前值(方框604)。然后,处理600确定是否有线程已经拥有要锁定的对象的锁和/或胖锁是否与该对象相关联(即,是否存在该对象的锁拥有者,或是否锁拥有者被设置成NULL值)(方框612)。如果不存在线程拥有者且瘦锁与该对象相关联(即,瘦锁拥有者字段362为NULL值)(方框612),以及由此该对象的锁是被解锁的,则处理600通过将该锁的瘦锁拥有者ID(例如,瘦锁拥有者ID358)设置成表示该线程的值(例如,惟一的线程标识符值),而为该线程获取该对象的瘦锁(方框616)。然而,如果处理600确定已存在锁拥有者和/或胖锁与该对象相关联(即,瘦锁拥有者字段362并非为NULL值)(方框612),则处理600保持瘦锁拥有者ID358不变。
当第一线程已处在变为锁拥有者的期间时,为防止第二线程试图获取该锁,通常使用单个原子操作(例如,在属于英特尔安腾处理器家族的处理器上的cmpxchg指令)实现方框604、612和616。如上所述,原子操作使线程(和/或在多处理器系统中的处理器)在原子操作执行期间对共享存储器进行排他性访问。从而,没有其他线程能够在原子操作期间修改由该原子操作所访问的存储单元。例如,可基于以下指令序列,在属于英特尔安腾处理器家族的处理器上实现在方框604、612和616处执行的处理ar.ccv=mov0r1=cmpxch2.acq[r3],r2在以前的指令中,寄存器r1可用于表示先前锁拥有者,寄存器r2可用于表示当前线程,寄存器r3可保持与目前瘦锁拥有者字段362相对应的地址。第一个指令(ar.ccv=mov0)将ar.ccv寄存器设置成零(即,NULL值)。第二个指令(r1=cmpxchg2.acq[r3],r2)为可用于实现以下操作的原子指令1)将先前锁拥有者设置成等于目前瘦锁拥有者字段362(即,r1=[r3]);2)检查目前瘦锁拥有者字段362是否为NULL值(即,[r3]是否等于ar.ccv);3)如果目前瘦锁拥有者字段362为NULL值(即,如果[r3]等于ar.ccv),将瘦锁拥有者ID358设置成表示当前线程的值(即,[r3]=r2);以及4)如果目前瘦锁拥有者字段362并非为NULL值(即,如果[r3]不等于ar.ccv),则保持瘦锁拥有者ID358不变(即,保持[r3]不变)。
返回图6,在确定了瘦锁拥有者字段362并非为NULL(方框612)或瘦锁拥有者ID358被设置成当前线程(方框616)之后,处理600确定该对象的先前锁拥有者是否为NULL值(对应于在方框616处当前线程已获取瘦锁的情形)(方框620)。如果先前锁拥有者为NULL值(方框620),则控制进行到方框624。然而,如果处理600确定先前锁拥有者并非为NULL值(方框620),则该处理确定先前锁拥有者是否为当前线程(对应于当前线程先前已获取该对象的瘦锁的情形)(方框626)。如果先前锁拥有者为当前线程(方框626),那么,控制进行到方框624。然而,如果处理600确定先前锁拥有者并非为当前线程(方框626),且由此确定另一线程已拥有该锁或胖锁与该对象相关联,则处理600将胖锁标志设置成TRUE(真),以指示胖锁与、或者将与该对象相关联(方框628)。然后,处理600调用已知的锁膨胀/竞争过程,以允许在目前锁拥有者(若有的话)释放该锁之后,当前线程获取该对象的胖锁(方框630)。处理600可导致当前线程在执行循环中旋转,或暂停执行直至目前锁拥有者(若有的话)释放/解锁该对象的锁。在该对象的锁变为可用之后,处理600则可为当前线程获取胖锁。另外,由于方框630的锁膨胀/竞争过程完成之后将不存在先前锁拥有者,处理600可将先前锁拥有者重置成NULL值(方框632)。然后,控制进行到方框624。
在方框624处,当前线程执行与被锁定对象相对应的代码的临界区。在代码的该临界区的执行完成后,处理600确定胖锁是否与该对象相关联(例如,胖锁标志是否为TRUE)(方框636)。如果瘦锁与该对象相关联(即,胖锁标志为FALSE),则处理600将该锁的瘦锁拥有者ID358重置成先前锁拥有者(方框640)。通过将瘦锁拥有者ID358重置成等于先前锁拥有者,处理600在先前拥有者为NULL值时对该锁进行解锁,或者在先前锁拥有者为当前线程时为当前线程保持该锁。然而,如果胖锁与该对象相关联(即,胖锁标志为TRUE),则处理600调用已知的胖锁释放过程来释放该对象的胖锁(方框644)。当在方框640或644处的处理完成之后,示例性处理600结束。
为支持递归的乐观平衡锁同步(以及以下所述的不平衡锁获取和释放过程),锁管理器200和/或锁管理器处理500利用一个或多个同步映射来存储/跟踪调用乐观平衡锁同步的方法(例如,JAVA方法)的每个实例的任何或所有的活动乐观平衡获取操作的状态。用于表示活动乐观平衡获取操作的状态的示例性同步映射表项包括锁地址、先前锁拥有者值和胖锁标志。同步映射的每个表项可被存储在调用堆栈中与调用乐观平衡锁同步的方法的特定实例相对应的调用帧内(从而支持由嵌套调用同一方法导致的递归锁获取)。如以下更详细描述的,不平衡锁获取和释放操作可遍历该同步映射,以确定在调用堆栈上活动的乐观平衡获取操作的数量,并按照需要对这样的操作进行修改。
图7示出可用于执行在图5的方框512处的处理和/或实现图2的不平衡锁获取单元224的示例性不平衡锁获取处理700。示例性不平衡锁获取处理700开始于将与锁的先前锁拥有者相对应的变量/寄存器设置成等于与该对象锁相关联的目前瘦锁拥有者字段(例如,图3B的瘦锁拥有者字段362)(方框708)。然后,处理700确定是否有线程已拥有待锁定对象的锁和/或胖锁是否与该对象相关联(即,是否将瘦锁拥有者字段362设置成NULL值)(方框712)。如果线程拥有者不存在以及瘦锁与该对象相关联(即,瘦锁拥有者字段362被设置成NULL值)(方框712),且由此该对象的锁是被解锁的,那么处理700通过将该锁的瘦锁拥有者ID(例如,瘦锁拥有者ID358)设置成表示该线程的值(例如,惟一的线程标识符值)来为该线程获取该对象的瘦锁(方框716)。然而,如果处理700确定锁拥有者已存在和/或胖锁与对象相关联(即,瘦锁拥有者字段362未被设置为NULL值)(方框712),则处理700保持瘦锁拥有者ID358不变。
如先前所述,当在第一线程已处在成为锁拥有者的处理期间,为防止第二线程试图获取该锁,通常使用单个原子操作(例如,在属于英特尔处理器家族的处理器上的cmpxchg指令)实现方框708、712和716。原子操作使得线程(和/或在多处理器系统中的处理器)在原子操作执行期间可对共享存储器进行排他性访问。从而,不会有任何其他线程能够在原子操作执行期间修改由该原子操作访问的存储单元。
返回图7,在确定出瘦锁拥有者字段362并非为NULL(方框712)或瘦锁拥有者ID358被定义成当前线程(方框716)之后,处理700确定该对象的先前锁拥有者是否为NULL值(对应于当前线程已在方框716处获取瘦锁的情形)(方框720)。如果先前锁拥有者为NULL值(方框720),则处理700将锁递归计数器设置成等于零来为膨胀该对象的锁做准备(方框724)。将锁递归计数器设置成零以指示正在执行该对象的第一次锁获取。然后,基于比锁递归计数器值多一的该对象锁的递归锁获取的数量,处理700调用已知的锁膨胀过程(方框728)。对于该情形,锁递归计数器为零,并由此锁膨胀过程是基于该锁的一个获取。然后,示例性处理700结束。
然而,如果处理700确定先前锁拥有者并非为NULL值(方框720),则该处理确定先前锁拥有者是否为当前线程(相当于当前线程先前已获取该对象的瘦锁的情形)(方框732)。如果先前锁拥有者为当前线程(方框732),则处理700调用一过程来修改存储在与待锁定对象相对应的同步映射中的活动乐观平衡获取操作的状态,来为膨胀该对象的锁做准备(方框736)。该修改活动获取过程可对同步映射进行处理,以便确定与该对象相对应的递归乐观平衡锁获取的数量,以及将相应的胖锁标志变为TRUE,以指示胖锁将与该对象相关联(由于不平衡锁获取正由处理700执行)。用于实现在方框736处执行的处理的示例性过程如图9所示,并在以后进行更详细的讨论。
当修改活动获取过程完成后(方框736),处理700将与该对象的锁相对应的锁递归计数器设置成等于由修改活动获取过程所确定的活动乐观平衡锁获取的数量(方框740)。然后,处理700基于比锁递归计数器值多一的该对象锁的递归锁获取的数量,调用已知的锁膨胀过程(方框728)。对于该情形,锁膨胀过程是基于活动乐观平衡锁获取加一个非平衡锁获取的数量的(相当于比在方框740处确定的锁递归计数器的值多一)。然后,示例性处理700结束。
然而,如果处理700确定先前锁拥有者并非为当前线程(方框732),且由此另一线程已经拥有该锁或胖锁已与该对象相关联,则处理700调用已知的锁膨胀/竞争过程,以允许在目前锁拥有者(如果有的话)释放该锁之后,当前线程获取该对象的胖锁(方框744)。处理700可导致当前线程在执行循环中旋转或暂停执行,直至目前锁拥有者(若有的话)释放/解锁该对象的锁。在该对象的锁变得可用后,处理700则可为当前线程获取该胖锁。另外,由于在方框744的锁竞争过程完成之后不会再有先前锁拥有者,处理700可将先前锁拥有者重置成NULL值(方框748)。然后,示例性处理700结束。
图8示出可用于执行在图5的方框516处的处理和/或用于实现图2的不平衡锁释放单元228的示例性不平衡锁释放处理800。示例性不平衡锁释放处理800开始于将与锁的先前锁拥有者相对应的变量/寄存器设置成等于与该对象锁相关联的目前瘦锁拥有者字段(例如,图3B的瘦锁拥有者字段362)(方框804)。然后,示例性处理800确定先前锁拥有者是否与试图释放该对象锁的当前线程相对应(方框808)。如果先前锁拥有者与当前线程相对应(方框808),且由此当前线程拥有该对象的瘦锁,那么处理800调用一过程以修改存储在与待锁定对象相对应的同步映射中的活动乐观平衡获取操作的状态,来为膨胀该对象的锁做准备(方框812)。该修改活动获取过程可对同步映射进行处理,以确定与该对象相对应的递归乐观平衡锁获取的数量,以及将相应的胖锁标志变为TRUE,以指示胖锁将与该对象相关联(由于不平衡锁释放正在由处理800执行)。用于实现在方框812处执行的处理的示例性过程如图9所示,并在以后进行更详细的讨论。
当修改活动获取过程完成后(方框812),处理800将与该对象的锁相对应的锁递归计数器设置成等于由修改活动获取过程所确定的将要存储在同步映射中的活动乐观平衡锁获取的数量(方框816)。然后,处理800基于等于在方框816处所确定的锁递归计数器的值的该对象锁的递归锁获取的数量,调用已知的锁膨胀过程(方框820)。锁膨胀过程完成后(方框820),处理800调用已知的胖锁释放过程,以释放该对象的胖锁(方框822)。然后,示例性处理800结束。
然而,如果先前锁拥有者不与试图释放该锁的当前线程相对应(方框808),则处理800确定瘦锁是否与该对象相关联(方框824)。例如,处理800可基于与该对象的瘦锁相关联的锁形式位,例如图3B的锁形式位354,来进行这一确定。如果瘦锁与该对象相关联(方框824),且由此不拥有该瘦锁的线程正试图释放该对象锁(基于在方框808作出的确定),处理800使用已知的异常处理技术来抛出一个异常,以指示当前线程不正确地试图释放其不拥有的锁(方框828)。然而,如果瘦锁不与该对象相关联(方框824),且由此胖锁与对象相关联,那么,处理800调用已知的胖锁释放过程以释放该对象的胖锁(方框822)。在方框822或方框828处的处理完成之后,示例性处理800则结束。
图9中示出了用于修改在同步映射(例如,由图6的乐观平衡锁同步处理600或图2的乐观平衡锁同步单元220所保持的同步映射)中的活动乐观平衡获取的状态的处理900。示例性处理900可用于修改与一组活动乐观平衡锁获取相关联的锁形式标志,为膨胀与特定对象相关联的锁做准备。示例性处理900例如可由分别如图7和8所示的示例性不平衡锁获取处理700和/或不平衡锁释放处理800使用。具体而言,示例性处理900可被示例性处理700和/或800所调用,以实现图7的方框736和/或图8的方框812所执行的处理。示例性处理900还可用于实现图2的平衡释放跟踪器/修改器236。
参看图9,示例性处理900开始于例如,通过获得与正在处理的对象相关联的锁定字的地址,来获得与该对象相对应的锁(方框904)。然后,处理900将与活动乐观平衡获取的数量相对应的计数器初始化为零(方框908)。该初始化完成之后,处理900开始对调用堆栈中的每个调用帧进行迭代,以确定与在方框904处所选的对象锁相对应的活动乐观平衡获取的存在性。
处理900通过获得在调用堆栈上的下一调用帧,开始对调用堆栈的调用帧进行迭代(方框912)。处理900然后获得存储在正在处理的调用帧中的下一锁定对象的同步映射表项(方框916)。接着,处理900确定该同步映射表项是否与正在处理的对象锁相对应(方框920)。如果该同步映射表项不与正在处理的对象锁相对应(方框920),则处理900将与该对象锁的活动乐观平衡获取的数量相对应的计数器加一(方框924)。处理900还将在同步映射表项中的胖锁标志设置成TRUE,以指示胖锁将与该对象相关联(方框928)。
在方框928处的处理完成后,或如果该同步映射表项不与正在处理的对象锁相对应(方框920),则处理900确定正在处理的同步映射表项是否为正在处理的调用帧中最后的同步映射表项(方框932)。如果该同步映射表项不是最后的同步映射表项(方框932),则控制返回到方框916,在此,处理900获得存储在正在处理的调用帧中的下一个锁定对象的同步映射表项。然而,如果该同步映射表项为最后的同步映射表项(方框932),则处理900确定正在处理的调用帧是否为在调用堆栈中的最后的调用帧(以及从而确定是否到达同步映射的末端)(方框936)。如果调用帧不是最后的调用帧(方框936),则控制返回到方框912,在此,处理900继续处理下一个调用帧。然而,如果正在处理的调用帧是调用堆帧中的最后的调用帧(方框936),则处理900返回与正在处理的锁定对象相对应的活动乐观平衡获取的数量(方框944)。然后,示例性处理900结束。
为了有助于理解此处所述的方法、装置和制品,在图10A-10C中分别示出图2的示例性锁管理器和图5、6、7、8和9的示例性处理500、600、700、800和900的示例性操作。图10A-10C的示例性操作对应于由单个线程对两个对象的锁执行的锁获取和释放的序列。锁定序列由调用的各种方法A至C产生,这些方法需要将对象锁定,以便于执行这些方法。图10A示出示例性程序序列。图10B示出对于在该程序序列中两个点的示例性同步映射的表项。图10C示出在执行图10A的不平衡锁释放之前和之后与每个同步映射表项相关联的胖锁标志的状态。
参看图10A,示例性程序序列开始于方法A执行对于第一对象(obj1)的锁的第一乐观平衡获取(指令A1)。根据图6的处理600,与第一乐观平衡获取相关联的是包括第一胖锁标志(inflated1)和第一先前锁拥有者(threadID1)的第一同步映射表项。然后,方法A调用方法B(指令C1),这导致将图10B的相应同步映射表项C1存储在同步映射高速缓存区中。同步映射表项C1包括指向锁定对象obj1的堆栈单元或寄存器以及指向胖锁标志inflated1的堆栈单元或寄存器。
接着,方法B执行对于第一对象obj1的锁的第二乐观平衡获取(指令A2)和对于第二对象obj2的锁的第三乐观平衡获取(指令A3)。根据处理600,与第二乐观平衡获取相关联的是包括第二胖锁标志(inflated2)和第二先前锁拥有者(threadID2)的第二同步映射表项。同样,与第三乐观平衡获取相关联的是包括第三胖锁标志(inflated3)和第三先前锁拥有者(threadID3)的第三同步映射表项。然后,方法B调用方法C(指令C2),这导致将图10B的相应同步映射表项C2存储在同步映射高速缓存区中。同步映射表项C2包括与第一对象obj1相关联的第一组数据和与第二对象obj2相关联的第二组数据。第一组数据包括指向锁定对象obj1的堆栈单元或寄存器和指向胖锁标志inflated2的堆栈单元或寄存器。第二组数据包括指向锁定对象obj2的堆栈单元或寄存器和指向胖锁标志inflated3的堆栈单元或寄存器。
接下来,方法C对第一对象obj1执行不平衡锁释放。根据图8的处理800,不平衡释放调用修改活动获取过程,该修改活动获取过程修改与第一对象obj1相对应的活动乐观平衡获取,为膨胀与obj1相关联的锁做准备。图10C示出在执行不平衡锁释放(指令R3)之前和之后存储在同步映射中的胖锁标志的状态。如所预期的,在不平衡锁释放之前,与第一对象obj1相关联的胖锁标志(inflated1和inflated2)和与第二对象obj2相关联的胖锁标志(inflated3)全为FALSE,从而指示瘦锁与对象obi1和obj2相关联。当不平衡锁释放之后,将与第一对象obj1相关联的胖锁标志(inflated1和inflated2)设置成TRUE,以指示由于不平衡释放,胖锁将会与obj1相关联。然后,方法B对第二对象obj2和第一对象obj1执行乐观平衡释放(分别为指令R2和R3),方法A对第一对象obj1执行乐观平衡释放,示例性程序结束。
图11所示框图表示能够实现此处所披露的装置和方法的示例性计算机或处理器系统1100。计算机1100例如可为服务器、个人计算机、个人数字助理(PDA)、互联网装置、或任何其他类型的计算设备。
即时示例的系统1100包括处理器1112。例如,处理器1112可通过来自于奔腾_家族、安腾_家族或XScale_家族的一个或多个英特尔_微处理器实现。当然,也适于使用其他家族的其他处理器。包括一个或多个微处理器的处理器1112可用于实现图1的示例性应用环境100、图2的示例性锁管理器200和/或分别如图5、6、7、8和9所示的示例性处理500、600、700、800和900。
处理器1112通过总线1118与包括易失性存储器1114和非易失性存储器1116的主存储器进行通信。易失性存储器1114可通过静态随机存取存储器(SRAM)、同步动态随机存取存储器(SDRAM)、动态随机存取存储器(DRAM)、RAMBUS动态随机存取存储器(RDRAM)和/或任何其他类型的随机存取存储器设备实现。非易失性存储器116可通过闪速存储器和/或任何其他所需类型的存储设备实现。对于主存储器1114、1116的访问通常按传统方式通过存储器控制器(未示出)进行控制。
计算机1100还包括传统接口电路1120。接口电路1120可通过众所周知的任何类型接口标准(例如,以太网接口、通用串行总线(USB)、和/或第三代输入/输出(3GIO)接口)实现。
一个或多个输入设备1122与接口电路1120相连。输入设备1122允许用户对处理器1112输入数据和命令。输入设备可通过例如键盘、鼠标、触摸屏、跟踪板、跟踪球、isopoint和/或语音识别系统来实现。
一个或多个输出设备1124也与接口电路1120相连接。输出设备1124例如可通过显示设备(例如液晶显示器、阴极射线管显示器(CRT))、打印机和/或扬声器实现。因此,接口电路1120通常包括图形驱动器卡。
接口电路1120还包括诸如调制解调器或网络接口卡之类的通信设备,以便于通过网络1126(例如,以太网连接、数字用户线(DSL)、电话线、同轴电缆、蜂窝电话系统等)与外部计算机进行数据交换。
计算机1100还包括用于存储软件和数据的一个或多个大容量存储设备1128。这样的大容量存储设备1128的示例包括软盘驱动器、硬盘驱动器、光盘驱动器和数字通用盘(DVD)驱动器。大容量存储设备1128和/或易失性存储器1114可用于存储例如分别由图6、7、8和9所示的处理600、700、800和900所保持和修改的同步映射。
作为在诸如图11所示设备的系统中实现此处所述的方法和/或装置的可选实施例,此处所述方法和/或装置可替换地嵌入在诸如处理器和/或ASIC(专用集成电路)之类的结构中。
从以上可知,本领域普通技术人员应该理解,以上所披露的方法和装置可实现在静态编译器、受控运行时环境即时(JIT)编译器中,和/或直接实现在微处理器的硬件中,以实现在执行多个程序中的性能优化。
尽管此处描述了特定的示例性方法、装置和制品,但本专利的覆盖范围并不限于此。相反,本专利覆盖所有在字面上或者在等同方式下清楚地处于所附权利要求范围之内的方法、装置和制品。
权利要求
1.一种用于在受控运行时环境中锁定线程对象的方法,包括确定用于对与所述对象相对应的锁执行的锁定操作;如果所述锁定操作不是不平衡的,则对所述锁执行乐观平衡同步;以及如果所述锁定操作是不平衡的,则修改所述锁的锁形式。
2.如权利要求1所述的方法,还包括如果所述锁定操作是不平衡的,则执行所述锁的不平衡锁获取和所述锁的不平衡释放中至少之一。
3.如权利要求1所述的方法,其中,所述锁形式与第一锁形式和第二锁形式中至少之一相对应,且其中,如果所述锁形式与所述第一锁形式相对应,则修改所述锁形式包括将所述锁转换成与所述第二锁形式相对应。
4.如权利要求3所述的方法,其中,所述第一锁形式与瘦锁相对应,所述第二锁形式与胖锁相对应。
5.如权利要求1所述的方法,其中,所述乐观平衡同步包括设置锁形式标志以指示在所述乐观平衡同步期间所述锁的锁形式。
6.如权利要求1所述的方法,其中,所述乐观平衡同步包括所述锁的乐观平衡锁获取和所述锁的乐观平衡锁释放,且其中,基于所述锁的锁形式,执行所述乐观平衡锁获取和所述乐观平衡锁释放中至少之一。
7.如权利要求6所述的方法,其中,所述乐观平衡锁获取包括如果所述锁形式与第一锁形式相对应,则将先前锁拥有者设置成等于与所述锁相关联的锁拥有者字段。
8.如权利要求6所述的方法,其中,所述乐观平衡锁释放包括如果所述锁形式与第一锁形式相对应,则将与所述锁相关联的锁拥有者字段设置成先前锁拥有者。
9.如权利要求8所述的方法,其中,如果所述锁形式与所述第一锁形式相对应,若所述先前锁拥有者为空线程,则将所述锁解锁,若所述先前锁拥有者为所述线程,则保持所述锁。
10.如权利要求1所述的方法,其中,所述乐观平衡同步包括保持同步映射,该同步映射用于存储与对所述对象的锁执行的一组乐观平衡同步相关联的一组活动乐观平衡获取状态。
11.如权利要求10所述的方法,还包括如果所述锁定操作是不平衡的,则执行所述锁的不平衡获取和所述锁的不平衡释放中至少之一,且其中,执行所述不平衡获取和所述不平衡释放中至少之一包括确定存储在所述同步映射中的活动乐观平衡获取状态的数量。
12.如权利要求11所述的方法,其中,修改所述锁的锁形式包括确定与存储在所述同步映射中的活动乐观平衡获取状态的数量相对应的锁递归计数值。
13.如权利要求10所述的方法,其中,所述同步映射包括与所述一组活动乐观平衡获取状态相对应的一组同步映射表项,且其中,在所述一组同步映射表项中的同步映射表项包括所述锁的先前锁拥有者和与所述锁的锁形式相对应的锁形式标志中至少之一。
14.如权利要求13所述的方法,其中,修改所述锁的锁形式包括修改所述同步映射表项中的所述锁形式标志。
15.如权利要求1所述的方法,其中,确定对所述锁执行的锁定操作包括确定所述锁定操作是否为所述锁的乐观平衡同步、所述锁的平衡同步、所述锁的不平衡获取以及所述锁的不平衡释放中之一。
16.一种存储机器可读指令的制品,所述指令当被执行时,使得机器确定对与所述对象相对应的锁执行的锁定操作;如果所述锁定操作不是不平衡的,则执行所述锁的乐观平衡同步;以及如果所述锁定操作是不平衡的,修改所述锁的锁形式。
17.如权利要求16所述的制品,其中,所述锁形式与第一锁形式和第二锁形式中至少之一相对应,且其中,对于修改所述锁形式,如果所述锁形式与所述第一锁形式相对应,则所述机器可读指令使得所述机器将所述锁转换成与所述第二锁形式相对应。
18.如权利要求16所述的制品,其中,所述机器可读指令使得所述机器保持同步映射,该同步映射用于存储与一组活动乐观平衡获取状态相对应的一组同步映射表项,其中该组活动乐观平衡获取状态与对所述对象的锁执行的一组乐观平衡同步相关联,且其中,在该组同步映射表项中的同步映射表项包括所述锁的先前锁拥有者和与所述锁的锁形式相对应的锁形式标志中至少之一。
19.如权利要求18所述的制品,其中,如果对所述锁的锁定操作是不平衡的,则所述机器可读指令使得所述机器执行所述锁的不平衡获取和所述锁的不平衡释放中至少之一,且其中,对于执行所述不平衡获取和所述不平衡释放中至少之一,所述机器可读指令使得所述机器执行以下至少之一确定在所述同步映射中存储的活动乐观平衡获取状态的数量,和修改在所述同步映射的至少一个同步映射表项中的至少一个锁形式标志。
20.一种用于在受控运行时环境中锁定线程对象的装置,包括乐观平衡锁定同步单元,用于执行与所述对象相对应的锁的乐观平衡同步;以及平衡同步状态跟踪器/修改器,用于基于所述锁的不平衡锁获取和所述锁的不平衡锁释放中至少之一的出现,执行对所述乐观平衡同步单元的状态的确定和修改中至少之一。
21.如权利要求20所述的装置,其中,所述乐观平衡锁同步单元用于如果所述锁形式为第一锁形式,则通过将所述锁的先前锁拥有者设置成等于所述锁的锁拥有者字段,而获取所述锁;以及如果所述锁形式为所述第一锁形式,则通过将所述锁拥有者字段重新设置成等于所述先前锁拥有者,而释放所述锁。
22.如权利要求20所述的装置,其中,所述乐观平衡锁同步单元用于设置锁形式标志以指示在对所述锁执行乐观平衡同步操作期间所述锁的锁形式。
23.如权利要求20所述的装置,其中,所述乐观平衡锁同步单元包括同步映射,该同步映射用于存储与对所述对象的锁执行的一组乐观平衡同步相对应的一组活动乐观平衡获取状态。
24.如权利要求23所述的装置,其中,所述同步映射包括与所述一组活动乐观平衡获取状态相对应的一组同步映射表项,且其中,在所述一组同步映射表项中的同步映射表项包括所述锁的先前锁拥有者和与所述锁的锁形式相对应的锁形式标志中至少之一。
25.如权利要求24所述的装置,其中,所述平衡同步状态跟踪器/修改器用于实现以下至少之一通过确定存储在所述同步映射中的活动乐观平衡获取状态的数量来确定所述乐观平衡同步的状态;和通过修改在所述同步映射的至少一个同步映射表项中的至少一个锁形式标志来修改所述乐观平衡同步单元的状态。
26.如权利要求20所述的装置,其中,所述乐观平衡同步包括所述锁的乐观平衡获取和所述锁的乐观平衡释放,且其中,所述乐观平衡同步单元用于基于所述锁的锁形式执行所述乐观平衡获取和所述乐观平衡释放中至少之一。
27.如权利要求20所述的装置,还包括用于执行所述锁的不平衡获取的不平衡锁获取单元和用于执行所述锁的不平衡释放的不平衡锁释放单元中至少之一,且其中,所述不平衡锁获取单元和所述不平衡锁释放单元中的所述至少之一用于修改所述锁的锁形式。
28.一种用于在受控运行时环境中锁定线程对象的系统,包括处理器,用于确定用于对与所述对象相对应的锁执行的锁定操作;如果所述锁定操作不是不平衡的,则执行所述锁的乐观平衡同步;以及如果所述锁定操作是不平衡的,则修改所述锁的锁形式;和存储器,用于存储所述锁的锁拥有者字段、所述锁的先前锁拥有者和与所述锁的锁形式相对应的锁形式标志中至少之一。
29.如权利要求28所述的系统,其中,所述处理器用于在所述存储器中存储同步映射,该同步映射包括与一组活动乐观平衡获取状态相对应的一组同步映射表项,其中该组活动乐观平衡获取状态与对所述对象的锁执行的一组乐观平衡同步相关联,且其中,在该组同步映射表项中的同步映射表项包括所述锁的先前锁拥有者和与所述锁的锁形式相对应的锁形式标志中至少之一。
30.如权利要求29所述的系统,其中,如果对所述锁的锁定操作是不平衡的,则所述处理器用于执行所述锁的不平衡获取和所述锁的不平衡释放中至少之一,且其中,对于执行所述不平衡获取和所述不平衡释放中至少之一,所述处理器用于实现以下至少之一确定存储在所述同步映射中的活动乐观平衡获取状态的数量,和修改在所述同步映射的至少一个同步映射表项中的至少一个锁形式标志。
全文摘要
本发明披露了用于受控运行时环境的利用锁膨胀进行线程同步的方法和装置。此处所披露的示例性方法包括确定用于对与所述对象相对应的锁执行的锁定操作;如果所述锁定操作不是不平衡的,则执行所述锁的乐观平衡同步,如果所述锁定操作是不平衡的,则修改所述锁的锁形式。
文档编号G06F9/45GK1997968SQ200580017334
公开日2007年7月11日 申请日期2005年6月10日 优先权日2004年6月28日
发明者塔蒂亚娜·施佩斯曼, 阿里-列扎·阿德-塔巴塔巴伊, 布赖恩·墨菲 申请人:英特尔公司(特拉华公司)
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1