zoukankan      html  css  js  c++  java
  • synchronized 学习,偏向锁,轻量级锁,重量级锁介绍

    Synchronized

    1 加锁方式

    • 修饰实例方法 -- > 锁的是当前实例
    • 修饰静态方法 -- > 锁的是当前类 例如Demo.class
    • 修饰代码块 -- > 看具体锁对象分析

    2 锁的存储

        private static  Object obj = new Object();
        public void add() {
            synchronized (obj){
                count++;
            }
        }
        //分析,synchronized(lock)是基于lock这个对象的生命周期来控制粒度的,所以所得存储应该和lock对象有关,探究jvm源码得知,当某个对象被synchronized当成同步锁时,那么围绕这个锁的一系列操作都和Mark Word有关系。
    
    • 以32位虚拟机为例

    为什么任何对象都可以实现锁?

    每个Object在jvm都有一个native的C++对象进行对应,线程在获取锁的时候,实际上就是获得一个monitor(监视器)对象,monitor可以认为是一个同步对象,所有的java对象天生都携带monitor,多个线程访问同步代码块时,其实相当于去争抢监视器对象并修改对象中的锁标记

    3 锁升级

    3.1 偏向锁的获取和撤销

    hotspot虚拟机的作者调查发现,大部分情况下,加锁的程序不仅仅不存在线程竞争,而且总是由同一个线程获得锁,基于这样一个概率,synchronized在jdk1.6之后做了一些优化,引入了偏向锁和轻量级锁的概念

    • 基本原理

    在线程访问同步代码块的时候,会在对象头中存储当前线程的ID,后续这个线程进入和退出这个代码块的时候,不需要再次加锁和释放锁,而是直接比较对象头里面是否存储了指向当前线程的偏向锁,如果相等表示锁是偏向当前线程的,没必要再次进行获得锁

    • 执行步骤

    • 偏向锁的撤销

      偏向锁不存在撤销,如果cas失败,则会升级轻量级锁

    3.2 轻量级锁

    • 基本原理

    偏向锁升级为轻量级锁时,对象的markword也会进行相应的变化,升级过程如下

    (1) 线程在自己的栈桢中创建锁记录 LockRecord

    (2) 将锁对象的对象头中的MarkWord复制到线程的刚刚创建的锁记录中

    (3) 将锁记录中的 Owner 指针指向锁对象

    (4) 将锁对象的对象头的 MarkWord替换为指向锁记录的指针。

    • 执行步骤

    轻量级锁加锁过程中用到了自旋,默认自旋10次,可以通过 PreBlockSpin 修改, jdk1.6之后引入了自适应自旋锁

    3.3 重量级锁

    当轻量级锁膨胀为重量级锁后,意味着线程只能被挂起阻塞来等待被唤醒了

    任意线程对 Object(Object 由 synchronized 保护)的访问,首先要获得 Object 的监视器。如果获取失败,线程进入同步队列,线程状态变为 BLOCKED。当访问 Object 的前驱(获得了锁的线程)释放了锁,然后会唤醒阻塞在同步队列中的线程,使其重新尝试对监视器的获取。

    • 执行步骤

    4 线程间通信

  • 相关阅读:
    php操作redis cluster集群成功实例
    js算法-快速排序(Quicksort)
    如何编写自己的虚拟DOM
    一文带你看透kubernetes 容器编排系统
    SpringBoot AOP控制Redis自动缓存和更新
    机器学习中的numpy库
    时间戳转自定义日期格式和刚刚、十分钟前等友好日期格式
    Python数据处理实例
    Spark1.x和2.x如何读取和写入csv文件
    掌握这个Python小技巧,轻松构建cytoscape导入文件
  • 原文地址:https://www.cnblogs.com/gaojf/p/12721666.html
Copyright © 2011-2022 走看看