添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
耍酷的抽屉  ·  EmmyLua Attach ...·  1 年前    · 
近视的机器猫  ·  git 导出提交记录-掘金·  1 年前    · 

Java锁synchronized关键字学习系列之轻量级锁

轻量级锁加锁原理

  1. 在代码访问同步资源时,如果锁对象处于无锁不可偏向状态,JVM首先将在当前线程的 栈帧 中创建一条锁记录(lock record),用于存放:
  • displaced mark word:存放锁对象当前的mark word的拷贝(为了解锁的时候恢复给锁对象,后面会说)
  • owner指针:指向当前的锁对象的指针,在拷贝mark word阶段暂时不会处理它

所以现在在栈帧中的lock record中的displaced mark word 存放的是锁对象处于无锁不可偏向状态的mark word的拷贝。

  1. 在拷贝mark word完成后,首先会挂起线程,jvm使用CAS操作尝试将对象的 mark word中的 lock record 指针 指向栈帧中的锁记录。 这里我们来回顾一下对象头在不同锁状态下的结构。

前面说到当前的锁对象是无锁不可偏向状态的,在拷贝完mark word之后,就会尝试把除了标示位以外空间用来存放栈帧中lock record的地址。

并且会将锁记录中的owner指针指向锁对象的mark word。如下:

  • 如果CAS替换成功(说明当前锁对象的mark word跟栈帧中lock record中的displaced mark word是 一样 的),表示竞争锁对象成功,则将锁标志位设置成 00,并且现在 mark word中的 lock record 指针 指向栈帧中的锁记录,表示对象处于轻量级锁状态,执行同步代码中的操作。

  • 如果CAS替换失败(说明当前锁对象的mark word跟栈帧中lock record中的displaced mark word是 不一样 的),则 判断当前对象的mark word是否指向当前线程的栈帧

    • 如果是则表示当前线程已经持有对象的锁,执行的是synchronized的锁重入过程,可以直接执行同步代码块
    • 否则说明该其他线程已经持有了该对象的锁,如果在自旋一定次数后仍未获得锁,那么轻量级锁需要升级为重量级锁,将锁标志位变成10,后面等待的线程将会进入阻塞状态

上面这两张图都是参考别人的,参考链接在最下方。

轻量级锁释放锁原理

轻量级锁的释放同样使用了CAS操作,尝试将displaced mark word 替换回mark word(也就是把栈帧中lock record的displaced mark word 拷贝回锁对象的mark word),这时需要检查锁对象的mark word中lock record指针是否指向当前线程的锁记录:

  • 如果替换成功(锁对象的mark word中的lock record指针指向当前线程栈帧的lock record),则表示没有竞争发生,整个同步过程就完成了
  • 如果替换失败(锁对象的mark word中的lock record指针指向的不是当前线程栈帧的lock record),则表示当前锁资源存在竞争,有可能其他线程在这段时间里尝试过获取锁失败,导致自身被挂起,并修改了锁对象的mark word升级为重量级锁,最后在执行重量级锁的解锁流程后唤醒被挂起的线程

轻量级锁重入

synchronized是可以锁重入的,在轻量级锁的情况下重入也是依赖于栈上的lock record完成的。以下面的代码中3次锁重入为例:

synchronized (user){
    synchronized (user){
        synchronized (user){
            //TODO
 

轻量级锁的每次重入,都会在栈中生成一个lock record,但是保存的数据不同:

首次分配的lock record,displaced mark word复制了锁对象的mark word,owner指针指向锁对象。
之后重入时在栈中分配的lock record中的displaced mark word为null,只存储了指向对象的owner指针

轻量级锁中,重入的次数等于该锁对象在栈帧中lock record的数量,这个数量隐式地充当了锁重入机制的计数器。这里需要计数的原因是每次解锁都需要对应一次加锁,只有最后解锁次数等于加锁次数时,锁对象才会被真正释放。在释放锁的过程中,如果是重入则删除栈中的lock record,直到没有重入时则使用CAS替换锁对象的mark word。

轻量级锁与偏向锁类似,都是jdk对于多线程的优化,不同的是轻量级锁是通过CAS来避免开销较大的互斥操作,而偏向锁是在无资源竞争的情况下完全消除同步。

最后放一个图来展示一下偏向锁和轻量级锁的升级

synchronized和锁对象

再谈synchronized锁升级

synchronized轻量级锁的获取流程 | ProcessOn免费在线作图

轻量级锁的加锁过程 | ProcessOn免费在线作图,在线流程图

加锁 后何时解锁_轻量级锁加解锁过程详解

轻量级锁与偏向锁

带你彻底搞懂锁膨胀,偏向锁,轻量级锁,重量级锁

synchronized锁升级原理分析(偏向锁-轻量级锁-重量级锁)

文章目录Java锁synchronized关键字学习系列之轻量级锁轻量级锁加锁原理轻量级锁释放锁原理轻量级锁重入总结参考Java锁synchronized关键字学习系列之轻量级锁轻量级锁加锁原理在代码访问同步资源时,如果锁对象处于无锁不可偏向状态,JVM首先将在当前线程的栈帧中创建一条锁记录(lock record),用于存放:displaced mark word:存放锁对象当前的mark word的拷贝(为了解锁的时候恢复给锁对象,后面会说)owner指针:指向当前的锁对象的指针,在拷贝
volatile介绍 volatile概述 volatile是比synchronized关键字轻量级的同步机制,访问volatile变量时不会执行加操作,因此不会使执行线程阻塞。 volatile保证可见性和禁止指令重排序,底层是通过“内存屏障”来实现,但不保证原子性。 写入volatile变量相当于退出同步代码块,读取volatile变量相当于进入同步代码块。 volatile的使用场景 对变量的写入操作不依赖变量的当前值,或能确保只有单个线程更新变量的值; 该变量不会与其他状态变量一起纳入不变性条件;(该变量没有包含在其他变量的不变式) 在访问变量时不需要加SynchronizedJava解决并发问题的一种最常用的方法,也是最简单的一种方法。Synchronized的作用主要有三个:(1)确保线程互斥的访问同步代码(2)保证共享变量的修改能够及时可见(3)有效解决重排序问题。 Java每一个对象都可以作为,这是synchronize...
哈喽,大家好,我是江湖人送外号[道格牙]的子牙老师。 近期准备写一个专栏:从Hotspot源码角度剖析synchronized。前前后后大概有10篇,会全网发,写完后整理成电子书放公众号供大家下载。对本专栏感兴趣的、希望彻彻底底学明白synchronized的小伙伴可以关注一波。电子书整理好了会通过公众号群发告知大家。我的公众号:硬核子牙。 本篇文章给大家分享关于轻量级的所有。在synchronized的所有类型轻量级是最简单的,但是这个简单是相对的,如果不具备一些底层的思维及学习底层的办法,它的
synchronized升级[1] Java对象头[2] Mark word 结构[3] Monitor[4] synchronized升级无偏向(可关闭)轻量级重量级[5] synchronized流程[6] synchronized对比 [1] Java对象头 我们以 Hotspot 虚拟机为例,Hopspot 对象头主要包括两部分数据:Mark Word(标记字段) 和 Klass Pointer(类型指针) Mark Word:默认存储对象的HashCode,分代年龄和标志位信息。
我们现在利用socket写一个简单的远程调用。 最简单实现远程调用的方式就是我们有一个客户端,然后我们去请求连接服务端,然后和服务端建立连接。然后客户端发送请求参数给服务端,服务端的代码直接调用业务类的指定方法并传入参数,最后将方法返回的结果发送会给客户端。 代码示例: 这是我们的业务类,里面有我们客户端需要调用的方法。 package cn.itcast.bigdata.sock...
文章目录Java高性能本地缓存框架Caffeine如何使用缓存加载手动加载自动加载手动异步加载自动异步加载过期策略基于大小基于时间基于引用Caffeine.weakKeys()Caffeine.weakValues()Caffeine.softValues()缓存移除invalidate(Object key)方法invalidateAll(Iterable<?> keys)方法invalidateAll()方法移除监听器(RemovalListener)Writer统计参考源代码 Java高性
Javasynchronized关键字也是一种,它可以用来保证多线程访问共享资源时的线程安全性。 synchronized关键字可以用来修饰方法或代码块,在修饰方法时相当于对整个方法进行加,在修饰代码块时则需要指定一个对象,只有获得该对象的线程才能访问该代码块。在Java,每个对象都有一个内部,也称为监视器或对象,可以用来实现对对象的同步访问。 在synchronized关键字的实现,当一个线程尝试获取对象时,如果该对象已经被其他线程获取,那么该线程就会进入等待队列等待,直到该对象被释放为止。在Java 5之前,synchronized关键字的实现是基于操作系统的底层互斥量实现的,存在较大的性能开销。从Java 5开始,Java引入了基于CAS(Compare and Swap)机制的轻量级和偏向,以及基于自旋的自适应来优化synchronized关键字的性能,这些的实现都是在Java虚拟机实现的,避免了底层操作系统的调用。
react-window构造的虚拟列表使用react-resizable动态调整宽度和使用react-drag-listview拖拽变换列位置的问题 baidu_28739511: 你好,DragTable的代码能贴一下吗