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 线程间通信

  • 相关阅读:
    项目总结-驱虫市场电商数据挖掘
    电商数据处理项目
    Hive sql常用函数公式整理
    拉勾网‘数据分析师’职位招聘信息数据爬取
    鸢尾花数据(PCA主成分分析)
    项目总结-信用评分卡
    某保险公司参保客户分析
    Excel自定义格式参数
    VS2013创建ADO实体模型报:Microsoft.SqlServer.Management.Sdk.Sfc, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91
    AngularJS-学习
  • 原文地址:https://www.cnblogs.com/gaojf/p/12721666.html
Copyright © 2011-2022 走看看