Linux中国 Linux中国门户站!
设为主页 设为主页
收藏本站 收藏本站
 
当前位置 :首页 ->Linux技术 ->系统管理 ->正文

线程与锁

来源:Linux-cn.com 作者:Webmaster 时间:2007-05-05 点击: [收藏] [投稿]

  对于原子性(不可分的)64位的double和long类型的变量的值的一个实现是可以自由地执行load,store,read,和write活动;实际上,这是一种强有力的激励。而模型将它们分为两个32位的等份,是出于对一些普遍流行而不能提供高效率的,以64为位为基本单位的存储器的微处理器的原因。它可以将所有的内存简单地定义为单个的变量作为基本单位而不可分割;但复杂的定义是为了对现在硬件条件作出的符合实际的让步。在将来,这些让步可能会被消除。在此之间,程序员必须对明确的同步访问共离的double和long变量有足够的小心。

  锁的规则

  设T为一个线程,而L为一把锁。下面是T关于L而引发的活动的规则:

  ·在L上的T的lock活动只有当以下情况才发生:对于每个不同于T的线程S,L上的S引发的前置活动unlock的数目等于S上L的前置活动lock的数目。(只有一个线程在一个时期内被允许要求锁定,而且此外一个线程可能获得好几次锁定而且不放弃锁的使用权,直到与unlock活动执行的次数相匹配。)

  ·锁T上的线程T引发一次unlock活动只有当以下情况才会发生:在L上的T的前置运行的unlock活动的数目,明显地少于L上T的前置lock活动的数目。(一个线程不允许对不属于它的锁进行解锁)。

  关于锁,所有线程中引发的的lock和unlock活动是在一个全然有序的顺序中运行。这个顺序必须与每个线程的活动顺序相一致。

  锁与变量相交作用的规则

设T为任何一个线程,V为任何变量,而L为任何锁。以下是一些由T关于V和L所引发的活动的约束:

  ·在V上的T的assign活动与L上的T的unlock活动之间,一个V上的T引发的store活动必须涉于其间,此外,对应于store的write活动必须领先于unlock活动。(如果一个线程要引发任何一个lock的unlock,它必须首先将其所有的工作内存中的赋予的值复制到主存储器中。)

  ·在L上的T中的lock活动与V上的T引发的use或store活动中,V中的assign或load活动必须涉于其间;此外,如果是load活动,那么与load相应的read活动必须跟随在lock活动后(如果线程中的工作区上所有的变量被刷新,则lock活动引发;在使用use之前则这些变量须被赋值或从主存中载入。)

  volatile 变量的规则

如果一个变量被定义成’volatile’,那么有下面一些额外的规则约束每个线程设T为一个线程,V和W为volatile变量

  ·V上的T的use活动只有当如下情况发生时才有效:如果在V的T之前使用load,并且当load的下一个活动是use时引发load。Use被称为是相应的load活动的read活动的联合活动。

  ·在V上的T的store活动当遇到如下情况才引发:V上的T的前一个活动是assign,并且当下一个V上的T是store时才引发assign。Assign被称为对于store活动的write的联合活动。

  ·变量V上的线程T中,设活动A为use或assign,让活动F为与A联合的load或store活动。并且设活动P为相应于F的V的read或write活动。类似的,设B为变量W的T线程的use或assign活动,设G为联合于B的load和store函数,并且设Q为相应于G的W的read或write活动。如果A先于B,那么P必须先于Q。(volatile类型的变量的主要拷贝的活动在线程请求的情况下,以严密的顺序来引发。以volatile变量所引发的Load,store,read,和write活动是不可分的(原子性),即使类型是double或long。

  可预见的store活动

  如果一个变量没有定义成volatile,那么上面介绍的规则可能会稍微地放宽对store活动执行顺序的约束,则其可能会与规则规定的顺序不符。放宽目的是允许针对Java编译器进行优化,以使某些保护语义的适当同步程序的代码重整的执行效率提高,但是可能由于没有适当同步而使得内存活动的行为超出管理顺序的制约。

  假如一个V上的T引发的的store跟随在特定的assign后,而依靠上面所介绍的规则运行,并且之间没有load或assign干涉。那么这个store则向内存送人一个值就是assign向T线程的工作区送入的值。如果以下约束被遵守时,这个特别的规则允许store活动在assign活动之前代替产生:

  ·如果store活动产生,则assign活动被一起产生。(记住,只有这是实际发生的,并不是某个线程计划怎样做的情况下,才有这些约束。一个store在assign发生之前抛出一个异常是不公平的)。

  ·在重新定位的store和assign活动之间,不能有lock活动。

  ·在重新定位的store和assign活动之间,不能有V的load活动。

  ·在重新定位的store和assign活动之间,不能有其它的V的store。

  ·store向主存中送入的这个值就是assign将要在线程T的工作区内放入的值。

  这最后的一个特征引发了我们可预见地调用一个store活动的灵感:之前就可以知道它,什么值将要被assgin存放。实际上,早在优化编译代码时就要计算这个值(例如,计算没有副作用,并且没有异常发生就允许这样),较早地存放它们(例如在进入一个循环之前),并且将他们放放工作寄存器为下面的循环所用。

  讨论

  任何在锁与变量之间的联合都是纯粹的习惯用法。锁定概念地刷新在线程工作区中所有的变量,解锁则是将已经被线程赋值的变量强制写入主存。那么可能与锁相联合的特定对象或类纯粹是一个习惯。在一些应用程序中,经常地在对对象的实际变量访问之前,适当锁定对象,例如;同步方法是一种遵循这种习惯的便利的方式。在另一些应用程序中,这就足够通过使用一个简单的锁来同步访问一个巨大的对象的集体。

  如果一个线程只有在锁定一把特定的锁之后,而在相应的解开锁之前,使用一个特定的共享变量,那么线程将在lock活动之后,线程将读取主存储器中的共享变量的值,如果需要,并要将最近赋值到的变量值存回主存,那么在unlock活动之前。这样,通过对锁的这种相互排斥的规则,足够有能力保证的值通过共享变量在线程间传递。

  Volatile(非永久性变量)的规则有效地要求了通过一个线程,主存储器被volatile变量的每一个use和assign活动,在严格管理下所接触,并且主存储器以一个完全安排好的顺序被线程执行语议所接触。然而,这些内存活动并没有在永久性变量的read和write上编排过顺序。



 如果您对本文有任何疑问或者建议,请到讨论区发表您的意见: >> 论坛入口 <<



上一篇:Java的网络知识   下一篇:你的第一个Java(for UNIX(Linux))

文章评论】 【收藏本文】 【推荐好友】 【打印本文】 【我要投稿】 【论坛讨论
更多相关文章
Power by linux-cn.com 粤ICP备05006655号