JDK1.6 的锁概念辨析

 

偏向锁的目的是消除锁操作中的CAS原语带来的OS开销. CAS原语是由操作系统提供的. CAS在硬件上是由关中断实现的, 是非常高级别的指令, 必须在管态(特权态、核心态)完成. 大部分操作系统都不向用户程序开放RING0. 也就是说, 用户程序是进不了RING0的. 这是操作系统的实现基础 --- > 也可以算作垄断基础的一部分. 

因此CAS的开销其实不小. 它至少需要两个门描述符的切换操作才能完成. 切换本身开销当然不大, 不过修改一下几个CPU内部寄存器的值而已. 大的开销主要在于代码段的切换造成的执行环境变更 --->处理器可能由此抛弃所有的CACHE. 而访问CACHE与访问内存的效率据传相差100倍之多, 所以, 可想而知......

而偏向锁用来消除CAS OS原语的方法其实很简单: 让第一个加锁的线程在锁上留下自己的名字(这个不难做到, 因为很显然一个没有被任何线程获取的锁其线程字段为"空"), 然后每次任何线程尝试加锁时会拿这个名字跟自己的名字比对, 如果一样则不启动任何加锁, 如果不一样则启动加锁.

显然, 只有第一个加锁的线程才能享受到这种福利. 因为任何后来的线程都会在锁上发现"别人"的名字. 说它"偏向", 是相对名字比后的系统行为来说的: 当名字一样时, 它不做任何操作. 这意味着当在比对中发现名字一样时(其实也就是当第一个线程来尝试重复获取锁(在其它锁曾经尝试获取锁以前)时, ), 它不会带给这个线程任何(额外的---因为用户要的是锁, 而不是其它的东西)开销. 在这个意义上, 它"优待"了第一个加锁的线程. 并且显然, 这样的优待也只有第一个加锁的线程才能拥有. 因为所有后续加锁的线程都将因为发现争用而对当前锁启动真正的加锁流程.

也就是说,它的目的是为了消除除第一次CAS操作以外的,不存在争用情况下的后续加锁动作的CAS操作。而 这种优化又显然只有第一次加锁的线程才能得到,这就是Bias的来源: 因为消除CAS操作产生的资源节省,只给第一次加锁的线程。

可以看出,偏向锁的目的是为了在没有竞争的情况下,避免几乎全部的同步开销。其中包括CAS与OS互斥。而其中的CAS,基本上就是轻量级锁的全部开销了:轻量级锁其实是在OS以外VM的同步尝试。

JDK1.6 的锁概念辨析_第1张图片

JDK1.6 的锁概念辨析_第2张图片

上图所列,其实就是1.6以后的全部的锁。而其它的锁概念如适应性自旋,锁粗化,锁剔除,其实只是行为意义上的锁,并不是真正名词意义上的“锁”。指的其实都是对上图中锁的一些行为优化。

代码可能在下列几种情况下被调用:

1,单线程。无争用(也即无并发);

2,多线程。无争用(也即无并发);

3,多线程。有争用(也即有并发)。

1.6的三个锁层次则分别对应这三种情况:

1,偏向锁(无锁);

2,轻量级锁(VM级);

3,重量级锁(OS级)。

在一个真正的运行时,程序状态必然经历从单线程到多线程无争用到多线程有争用的过程。这正好为锁机制提供了一个逐渐提升锁级别的机会:

1,偏向锁在没有侦测到任何多线程访问的情况下,使系统工作在无锁状态。举个例子,在整个世界只有我一个人居住的情况下,我自然不需要锁。硬要启用这个锁,对我显然将形成一种不必要的负担;

2,轻量级锁在侦测到多线程,也就是说,在整个世界中发现其它人的情况下,我会开始需要一把锁。但是这把锁并不一定要求是互斥的。因为我从来没有发现过其它人在我在家的时候尝试过进入我的房间。在这种从来没有发生过冲突即锁竞争的情况下,互斥是不必要的。但是,锁仍然是必要的。因为它是系统过渡到重量级锁即互斥阶段的必要条件: 系统如何才能知道什么时候应该进入互斥阶段呢? 它必须先知道有一个人占用了锁, 然后才能在第二个人来请求锁的时候才能归纳得到系统当前处于互斥状态的信息。

JDK1.6 的锁概念辨析_第3张图片

因此可以看出,整个锁系统的逻辑是这样的:

1,如果没有发现多线程的踪迹,那么系统将不会进行任何与锁有关的操作;

2,如果发现了多线程的踪迹,系统将进入轻量级锁阶段。在这个阶段,系统将使用一个替换锁对象mark word的CAS原语来侦测冲突。所以严格上来说,轻量级锁并不是真正的锁,它只是一种用来侦测重量级锁边界条件的操作。所以整个从无锁即偏向锁向重量级锁升级的过程,其实就是系统提供的一种 逐渐进入 真正封锁状态的技术。所有重量级以前的锁,目的并不是为了封锁,因为在它以前并不存在真正的并发操作。所有这些所谓的“锁”,其本质上并不是“锁”。它们所提供的只不过一种使系统“逐渐进入”真正封锁状态的能力。它的哲学是这样的:根据系统的当前状态决定系统的行为(以及由这些系统行为所决定的用户级开销)。系统(或者说程序、临界代码)有三个状态:单线程,多线程,锁竞争。三种锁的提出,分别用来应对这三种状态。而所谓“锁”的逐渐升级过程,只不过是一种状态的逐渐提升过程而已。也就是说,除重量级锁以外所有的其它锁,它们所处理的东西从本质上来说并不是锁或互斥,而是状态侦测。与其命名为轻量级锁与偏向锁,还不如命名为状态侦测锁

因为偏向锁,轻量级锁,,,,这样的词真的很令人费解。

 

你可能感兴趣的:(锁优化,偏向锁)