Java 虚拟机对锁优化所作的努力

做为一款公用平台,JDK 自己也为并发程序的性能绞尽脑汁,在 JDK 内部也想尽一切办法提供并发时的系统吞吐量。这里,我将向你们简单介绍几种 JDK 内部的 "锁" 优化策略。数组

一、 锁偏向并发

锁偏向是一种针对加锁操做的优化手段。函数

若是一个线程得到了锁,那么锁就进入偏向模式。当这个线程再次请求锁时,无须再作任何同步操做。这样就节省了大量有关锁申请的操做,从而提升了程序性能。性能

所以,对于几乎没有锁竞争的场合,偏向锁有比较红啊的优化效果,由于连续屡次极有多是同一个线程请求相同的锁。而对于锁竞争比较激烈的场合,其效果不佳。由于在竞争激烈的场合,最有可能的状况是每次都是不一样的线程来请求相同的锁。点击这里了解几种常见的锁。优化

二、 轻量级锁ui

若是偏向锁失败,即上一个请求的锁的线程和这个线程不是同一个。偏向锁失败意味者不能避免作同步操做。此时,虚拟机并不会当即挂起线程。他会使用一种成为轻量级锁的优化手段。操作系统

轻量级锁的操做也很方便,它只是简单地将对象头部做为指针,指向蚩尤锁的线程堆栈的内部,来判断一个线程是否持有对象锁。 若是线程得到轻量级锁成功,则能够顺利进入临界区。若是轻量级锁失败,则表示其余线程抢先争夺了锁,那么当前线程的锁请求就会膨胀为重量级锁。点击这里了解几种常见的锁。线程

三、 自选锁指针

锁膨胀后,虚拟机为了不线程真实地在操做系统层面挂起,虚拟机还会在作最后的努力–自选锁。因为当前线程暂时没法得到锁,可是何时能够得到锁是一个未知数。也许在CPU几个时钟周期后,就能够获得锁。若是这样,简单粗暴的挂起线程多是一种得不偿失的操做,所以系统会进行一次赌注:它会假设在不久的未来,线程能够获得这把锁。server

所以虚拟机让当前线程作个空循环,在通过若干次循环后,若是能够获得锁,那么就顺利进入临界区。若是还不能获得锁,才会真实地将线程在操做系统层面挂起。

四、 锁消除

锁消除是一种更完全的锁优化。Java虚拟机在JIT编译时,经过对运行上下文的扫描,去除不可能存在共享资源竞争的锁。经过锁消除,能够节省毫无心义的请求锁时间。

下面这种这种状况,咱们使用vector, 而vector内部使用了synchronize请求锁。

publicString[]  createStrings(){     

      Vector  v=newVector();

       for(inti=0;i<100;i++){         

      v.add(Integer.toString(i));    

 }     

return v.toArray(newString[]{}); }

因为V只在函数 createStrnigs 中使用,所以它只是一个单纯的局部变量。局部变量是在线程栈上分配的,属于线程私有额数据,所以不可能被其余线程访问。因此,在这种状况下,Vector内部全部加锁同步都是没有必要的。若是虚拟机检测到这种状况,就会将这些无用的锁操做去除。点击这里了解几种常见的锁。

锁消除涉及的一项关键技术为逃逸分析。所谓逃逸分析就是观察某一个变量是否会逃出某一个做用域。在本例中,变量v显然没有逃出createString 函数以外。以此为基础,虚拟机才能够大胆的将v内部的加锁操做去除。若是createStrings 返回的不是String数组,而是v自己,那么就认为变量v逃逸出了当前函数,也就是说v有可能被其余线程访问。如是这样,虚拟机就不能消除v中的锁操做。

逃逸分析必须在 -server 模式下进行,可使用 -XX:DoEscapeAnalysis 参数打开逃逸分析,使用 -XX:+EliminateLocks 参数能够打开锁消除。

转:http://virtual.51cto.com/art/201809/583142.htm

相关文章
相关标签/搜索