精华内容
下载资源
问答
  • 偏向锁java_Java偏向锁

    2021-03-16 22:44:33
    概述偏向锁是JDK 1.6提出的一种锁优化方式,起核心思想是如果程序没有竞争,则取消之前已经取得锁的线程的同步操作。也就是说,某一个锁被一个线程获取之后,便进入了偏向锁模式,当该线程再次请求这个锁时,就无需...

    概述

    偏向锁是JDK 1.6提出的一种锁优化方式,起核心思想是如果程序没有竞争,则取消之前已经取得锁的线程的同步操作。也就是说,某一个锁被一个线程获取之后,便进入了偏向锁模式,当该线程再次请求这个锁时,就无需再进行相关的同步操作,从而节省了操作时间。但是如果在此期间,有其他线程申请了这个锁,则退出偏向锁模式。在JVM中可以使用-XX:+UseBiasedLocking设置启用偏向锁。

    实验

    看如下的代码:

    package com.winwill.lock;

    import java.util.List;

    import java.util.Vector;

    /**

    *@author qifuguang

    *@date 15/6/5 13:44

    */

    public class TestBiasedLock {

    private static List list = new Vector();

    public static void main(String[] args) {

    long tsStart = System.currentTimeMillis();

    for (int i = 0; i < 10000000; i++) {

    list.add(i);

    }

    System.out.println("一共耗费:" + (System.currentTimeMillis() - tsStart) + " ms");

    }

    }

    代码中使用一个循环一直往Vector中新增元素,Vector的add操作会请求锁:

    /**

    * Appends the specified element to the end of this Vector.

    *

    *@param e element to be appended to this Vector

    *@return {@code true} (as specified by {@link Collection#add})

    *@since 1.2

    */

    public synchronized boolean add(E e) {

    modCount++;

    ensureCapacityHelper(elementCount + 1);

    elementData[elementCount++] = e;

    return true;

    }

    我们使用如下的参数运行代码:

    -XX:+UseBiasedLocking

    -XX:BiasedLockingStartupDelay=0

    -Xmx512m

    -Xms512m

    -XX:BiasedLockingStartupDelay=0这个参数表示虚拟机一启动就启动偏向锁模式,因为默认情况下,虚拟机启动4s之后才会启动偏向锁模式,该例运行时间较短,故做此设置。

    得到如下结果:

    ed7fd002b1194ea85d38ea46a0725c8d.png

    但是,如果我们使用如下的参数运行程序:

    -XX:-UseBiasedLocking

    -Xmx512m

    -Xms512m

    得到的结果如下:

    8d7c0d4bbd31ca5c5b9c396e649d74fd.png

    结论

    偏向锁在少竞争的情况下,对系统性能有一定的帮助。

    注意事项

    偏向锁在竞争激烈的情况下没有太强的优化效果,因为大量的竞争会导致持有锁的线程不停地切换,锁也很难一直保持偏向模式,此时,使用偏向锁不仅不能优化程序,反而有可能降低程序性能。因为,在竞争激烈的场景下可以使用-XX:-UseBiasedLocking参数禁用偏向锁。

    展开全文
  • Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁...

    Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。

    偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。

    如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会尝试消除它身上的偏向锁,将锁恢复到标准的轻量级锁。(偏向锁只能在单线程下起作用)

    锁存在Java对象头里。如果对象是数组类型,则虚拟机用3个Word(字宽)存储对象头,如果对象是非数组类型,则用2字宽存储对象头。在32位虚拟机中,一字宽等于四字节,即32bit。

    机制:每个锁都关联一个请求计数器和一个占有他的线程,当请求计数器为0时,这个锁可以被认为是unhled的,当一个线程请求一个unheld的锁时,JVM记录锁的拥有者,并把锁的请求计数加1,如果同一个线程再次请求这个锁时,请求计数器就会增加,当该线程退出syncronized块时,计数器减1,当计数器为0时,锁被释放(这就保证了锁是可重入的,不会发生死锁的情况)。

    偏向锁,简单的讲,就是在锁对象的对象头中有个ThreaddId字段,这个字段如果是空的,第一次获取锁的时候,就将自身的ThreadId写入到锁的ThreadId字段内,将锁头内的是否偏向锁的状态位置1.这样下次获取锁的时候,直接检查ThreadId是否和自身线程Id一致, 如果一致,则认为当前线程已经获取了锁,因此不需再次获取锁,略过了轻量级锁和重量级锁的加锁阶段。提高了效率。

    但是偏向锁也有一个问题,就是当锁有竞争关系的时候,需要解除偏向锁,使锁进入竞争的状态。

    偏向锁的释放之后会进入到轻量级锁阶段,两个线程进入锁竞争状态,一个具体例子可以参考synchronized锁机制。

    synchronized锁流程如下:

    第一步,检查MarkWord里面是不是放的自己的ThreadId ,如果是,表示当前线程是处于 “偏向锁”

    第二步,如果MarkWord不是自己的ThreadId,锁升级,这时候,用CAS来执行切换,新的线程根据MarkWord里面现有的ThreadId,通知之前线程暂停,之前线程将Markword的内容置为空。

    第三步,两个线程都把对象的HashCode复制到自己新建的用于存储锁的记录空间,接着开始通过CAS操作,把共享对象的MarKword的内容修改为自己新建的记录空间的地址的方式竞争MarkWord,

    第四步,第三步中成功执行CAS的获得资源,失败的则进入自旋

    第五步,自旋的线程在自旋过程中,成功获得资源(即之前获的资源的线程执行完成并释放了共享资源),则整个状态依然处于 轻量级锁的状态,如果自旋失败

    第六步,进入重量级锁的状态,这个时候,自旋的线程进行阻塞,等待之前线程执行完成并唤醒自己

    因此 流程是这样的 偏向锁->轻量级锁->重量级锁(由这三个关键词串联起来的过程才是最重要的)

    总结:

    偏向锁,其实是无锁竞争下可重入锁的简单实现

    展开全文
  • Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种...

    Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。

    偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程争用的情况,则线程是不需要触发同步的,这种情况下,就会给线程加一个偏向锁。

    如果在运行过程中,遇到了其他线程抢占锁,则持有偏向锁的线程会被挂起,JVM会消除它身上的偏向锁,将锁恢复到标准的轻量级锁。

    它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。

    偏向锁的实现

    偏向锁获取过程:

    访问Mark Word中偏向锁的标识是否设置成1,锁标志位是否为01,确认为可偏向状态。

    如果为可偏向状态,则测试线程ID是否指向当前线程,如果是,进入步骤5,否则进入步骤3。

    如果线程ID并未指向当前线程,则通过CAS操作竞争锁。如果竞争成功,则将Mark Word中线程ID设置为当前线程ID,然后执行5;如果竞争失败,执行4。

    如果CAS获取偏向锁失败,则表示有竞争。当到达全局安全点(safepoint)时获得偏向锁的线程被挂起,偏向锁升级为轻量级锁,然后被阻塞在安全点的线程继续往下执行同步代码。(撤销偏向锁的时候会导致stop the word)

    执行同步代码。

    注意:第四步中到达安全点safepoint会导致stop the word,时间很短。

    偏向锁的释放:

    偏向锁的撤销在上述第四步骤中有提到。偏向锁只有遇到其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁,线程不会主动去释放偏向锁。偏向锁的撤销,需要等待全局安全点(在这个时间点上没有字节码正在执行),它会首先暂停拥有偏向锁的线程,判断锁对象是否处于被锁定状态,撤销偏向锁后恢复到未锁定(标志位为“01”)或轻量级锁(标志位为“00”)的状态。

    偏向锁的适用场景

    始终只有一个线程在执行同步块,在它没有执行完释放锁之前,没有其它线程去执行同步块,在锁无竞争的情况下使用,一旦有了竞争就升级为轻量级锁,升级为轻量级锁的时候需要撤销偏向锁,撤销偏向锁的时候会导致stop the word操作;

    在有锁的竞争时,偏向锁会多做很多额外操作,尤其是撤销偏向所的时候会导致进入安全点,安全点会导致stw,导致性能下降,这种情况下应当禁用;

    �.T}�D

    展开全文
  • 偏向锁当只有一个线程多次重复抢占锁同一资源时,即使是轻量级锁每次也至少需要两次(加锁、解锁)CAS操作。而此场景经Hotspot统计是比较容易出现的。所以为了减少不必要的资源浪费,偏向锁应运而生。优点只需要执行一...

    偏向锁

    当只有一个线程多次重复抢占锁同一资源时,即使是轻量级锁每次也至少需要两次(加锁、解锁)CAS操作。而此场景经Hotspot统计是比较容易出现的。所以为了减少不必要的资源浪费,偏向锁应运而生。

    优点

    只需要执行一次CAS即可获取锁

    采用延迟释放锁策略

    锁重入时,只需要判断mark_word.threadId(关于对象头的文章)是否为当前threadId即可

    缺点

    总体上只针对第一个线程有效,新线程获取锁时,会导致锁膨胀

    锁膨胀时,会导致stop the world (STW)

    与原生hashcode()互斥,导致偏向锁并非适应于所有的instance

    如何获取一把偏向锁

    前提

    JVM偏向锁(-XX:+UseBiasedLocking)默认已开启

    确认instance可用偏向锁可用,即mark word 锁状态标记位为 01

    分支条件

    匿名偏向

    若instance处于匿名偏向状态(即初始状态,threadId为null),则执行CAS操作,将当前线程的id赋值到对象的mark word中,若成功则获取偏向锁成功,否则说明有多个线程竞争资源需要进行锁膨胀。

    重偏向

    即instance的Mark Word里的epoch与与klassOop.epoch标志位不一致时,表示此instance可被重偏向,此时新线程可以执行CAS操作进行锁抢占。

    已偏向

    即threadId已存在,且instance的epoch有效(与klassOop.epoch相等)此时instance处于已偏向状态。此时需比较当前threadId与mark_word.threadId的值,若相等,则可以继续占有锁,否则说存在资源竞争,需要进行锁膨胀。

    锁膨胀过程

    所有要竞争锁的线程到达安全区后,挂起对应线程。

    遍历原锁持有线程的的调用栈的锁记录。将与被锁instance相关的锁记录改为轻量级锁相关的值。

    更改被锁instance的Mark Word,将其指向最早的锁记录。

    释放被挂起的相关线程。

    偏向锁的骚操作

    批量重偏向

    Mark Word 里与偏向锁有关的信息除了threadId还有epoch,前面也提到epoch可以用来判断是否可以重偏向。那么他是如何实现的呢?

    批量重偏向是针对两个线程串行共享instance资源场景(一个线程初始化instance传递给另一个线程)的优化。因为此时两个线程并不存在竞争,所以第二个线程可以继续使用偏向锁。

    实现前提

    Hotspot 通过在klassOop(可以理解为类的原型,其结构与instance一致)。里添加一个epoch字段,当一个Klass实例化instance一个时,便会以klassOop为原型初始化,epoch便被初始化在了instance的Mark Word中。

    重偏向过程

    当JVM执行到一个全局安全点的时候,挂起所有线程。

    给KlassOop.epoch + 1.

    给所有被偏向锁锁住的instance的Mark Word中的epoch + 1。或者采用启发式撤销偏向锁。

    释放线程。

    启发式撤销偏向

    启发式撤销偏是针对重偏向的一种预防式优化。其逻辑很简单,通过设置一个阈值(k),一但epoch>k则执行撤销偏向锁操作,否者可以执行重偏向操作。

    关于偏向锁的JVM参数

    启用偏向锁

    -XX:+UseBiasedLocking

    偏向锁的延迟启动时间

    偏向锁默认是在JVM启动4s后再初始化偏向锁,可用如下参数修改启动时间,设为0则表示立即启用。之所以这么设计是因为JVM启动的时候,如果立即启动偏向,有可能会因为线程竞争太激烈导致产生太多安全点挂起。

    -XX:BiasedLockingStartupDelay=0

    参考

    展开全文
  • JDK 1.6 为了减少"重量级锁"的性能消耗,引入了“偏向锁”和“轻量级锁”,锁一共拥有4种状态:无锁状态、偏向锁、轻量级锁、重量级锁。锁状态是通过对象头的Mark Word来进行标记的:锁可以升级但不能降级,意味着...
  • 偏向锁实现原理偏向锁,顾名思义,它会偏向于个访问锁的线程,如果在接下来的运行过程中,该锁没有被其他的线程访问,则持有偏向锁的线程将永远不需要触发同步。如果在运行过程中,遇到了其他线程抢占锁,则持有偏向...
  • 为什么需要偏向锁当多个处理器同时处理的时候,通常需要处理互斥的问题。一般的解决方式都会包含acquire和release这个两种操作,操作保证,一个线程在acquire执行之后,在它执行release之前,其它线程不能完成...
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程...
  • 可以参考我的一篇博文:Java轻量级锁原理详解(Lightweight Locking)Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。轻量级锁也是一种...
  • 今天我们来聊聊 Synchronized 里面的各种锁:偏向锁、轻量级锁、重量级锁,以及三个锁之间是如何进行锁膨胀的。众所周知,线程阻塞带来的上下文切换的代价是很大的,Java 为了尽量减少上下文的切换从而引入了更多的...
  • 1.偏向锁偏向锁是JDK1.6提出来的一种锁优化的机制。其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作。也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,就无需再...
  • 1.偏向锁的获取逻辑主要在汇编实现的 biased_locking_enter 方法中请求线程进入这个方法之后,会直接判断锁依赖对象的对象头是否有 偏向锁 成分(101是偏向锁成分)。如果没有,直接跳出,退出后直接尝试把自己栈上的...
  • Java锁的种类:偏向锁,轻量级锁...以前是只有重量级锁这个分类,但是自从JDK6引入了偏向锁和轻量级锁之后,锁的种类就有下面三种了:偏向锁轻量级锁重量级锁Java锁存储的地方任何对象都可以作为锁,那么锁信息又存...
  • Java偏向锁(Biased Locking)是Java 6引入的一项多线程优化。它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。轻量级锁也是一种多线程优化,它与偏向锁的区别在于,轻量级锁是通过CAS来避免进入...
  • 网上有许多讲偏向锁,轻量级锁的文章,但对偏向锁如何升级讲的不够明白,有些文章还相互矛盾,经过对jvm源码(biasedLocking.cpp)的仔细分析和追踪,基本升级过程有了一个清晰的过程,现将升级流程阐述如下:因为偏向锁,...
  • Java对象头与Monitorjava对象头是实现synchronized的对象的基础,synchronized使用的对象是存储在Java对象头里的。对象头包含两部分:Mark Word 和 Class Metadata Address其中Mark Word在默认情况下存储着对象...
  • Java 偏向锁

    2018-07-15 17:43:14
    Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。它通过消除资源无竞争情况下的同步原语,进一步提高了程序的运行性能。 偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在接下来的运行过程中,该...
  • 该楼层疑似违规已被系统折叠隐藏此楼查看此楼Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。偏向锁,顾名思义,它会偏向于第一个访问锁的线程,如果在运行过程中,同步锁只有一个线程访问,不存在多线程...
  • java 偏向锁

    千次阅读 2019-07-23 22:30:52
    文章目录偏向锁1、偏向锁是什么2、优缺点优点缺点3、偏向锁怎么获取前提4、偏向锁的撤销5、可重偏向状态(Rebiasable)6、BiasedLockingBulkRebiasThreshold 参数是干什么用的7、到BiasedLockingBulkRevokeThreshold ...
  • 偏向锁当锁对象第一次被线程获取时,虚拟机会把对象头的锁状态标志设置为01(即偏向状态),同时,使用CAS操作把获取到这个锁的线程的ID记录在对象头的mark word中。如果这个CAS操作成功,那么,以后持有这个偏向锁的...
  • java中每个对象都可作为锁,锁有四种级别,按照量级从轻到重分为:无锁、偏向锁、轻量级锁、重量级锁。每个对象一开始都是无锁的,随着线程间争夺锁,越激烈,锁的级别越高,并且锁只能升级不能降级。一、java对象头...
  • 原标题:Java知识进阶-程序员彻底理解偏向锁原理-知识铺知识铺: 致力于打造轻知识点,持续更新每次的知识点较少,阅读不累。不占太多时间,不停的来唤醒你记忆深处的知识点。一、使用场景被synchronized修饰的方法...
  • Java偏向锁

    千次阅读 2015-06-05 14:07:45
    概述偏向锁是JDK 1.6提出的一种锁优化方式,起核心思想是如果程序没有竞争,则取消之前已经取得锁的线程的同步操作。也就是说,某一个锁被一个线程获取之后,便进入了偏向锁模式,当该线程再次请求这个锁时,就无需...
  • 1 Java 对象头Java 对象头是 Synchronized 机制的基础,相关信息存储在 Java 对象头里面。对象头有两种形式,普通对象和数组对象,以32位JVM为例:普通对象的对象头:数组对象的对象头:其中 Klass Word 是执行...
  • 文章目录声明本文是笔者在阅读周志明老师的《深入理解Java虚拟机》后,将相关知识点思考、转化为自己的理解并输出,如果有理解不到位的地方,欢迎指正!1 Java对象头在HotSpot虚拟机里,对象在堆内存中的存储布局...
  • http://kenwublog.com/theory-of-java-biased-locking阅读本文...可以参考我的一篇博文:Java轻量级锁原理详解(Lightweight Locking)Java偏向锁(Biased Locking)是Java6引入的一项多线程优化。它通过消除资源无竞争...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,771
精华内容 1,108
关键字:

偏向锁java

java 订阅