synchronized

JAVA使用synchronized实现互斥同步线程安全以及原理
  1. synchronized经过编译后会在同步代码块前后形成monitorenter和monitorexit,
    任何对象都有一个 Monitor 与之相关联,当且一个 Monitor 被持有之后,他将处于锁定状态。
    线程执行到 monitorenter 指令时,将会尝试获取对象所对应的 Monitor 所有权,即尝试获取对象的锁,
    如果当前线程拥有那个对象的锁,把锁的计数器+1,相应的但执行monitorexit指令时会把锁的计数
    器-1即释放锁!
锁优化
  1. jdk1.6之后引入一项锁优化,加入偏向锁,轻量级锁

    1. 轻量级锁:主要是为了减少传统的重量级锁使用操作系统互斥产生的性能消耗
      (因为重量级锁如果要阻塞或者唤醒一个线程,都需要操作系统介入,
      需要从用户态切换为核心态,在状态切换需要消耗处理器时间)。
      如果有多线程竞争同一把锁,则会膨胀为重量级锁竞争,该锁的获取与释放需要CAS操作

    2. 偏向锁:主要是消除数据在无竞争的情况下同步,在线程执行过程中,该锁没有被其他线程获取,则持有偏向锁的线程
      将永远不需要再进行同步,减少CAS操作

  2. 轻量级锁获取流程

    Mark Word:每个对象的对象头信息,该对象头分为两部分信息的。
    第一部分:存储对象自身运行时的数据,如哈希码,GC分代年龄,是实现轻量级锁与偏向锁关键
    第二部分:存储指向方法区对象类型数据的指针

    1. 当线程访问同步代码块,会先检查该同步对象是否被锁定,如果没有则 JVM 首先将在当前线程的栈帧中,
      建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的 Mark Word的 拷贝
      (官方把这份拷贝加了一个 Displaced 前缀,即 Displaced Mark Word),否则执行 3

    2. JVM 利用 CAS 操作尝试将对象的 Mark Word 更新为指向 Lock Record 的指正。如果成功,
      表示竞争到锁,则将锁标志位变成 00(表示此对象处于轻量级锁状态)。否则执行 3

    3. 判断当前对象的 Mark Word 是否指向当前线程的栈帧?如果是,则表示当前线程已经
      持有当前对象的锁,则直接执行同步代码块;否则,只能说明该锁对象已经被其他线程
      抢占了,此时轻量级锁膨胀为重量级锁,锁标志状态值变为 10,后面等待的线程也要进入
      阻塞状态

  3. 释放锁

    1. 取出在获取轻量级锁保存在 Displaced Mark Word 中 数据

    2. 使用 CAS 操作将取出的数据替换当前对象的 Mark Word 中。
      如果成功,则说明释放锁成功;否则说明有其他线程尝试获得
      该锁,要在释放锁的同时唤醒被挂起的锁

  4. 偏向锁

    1. 在jdk1.6之后,当锁对象第一次被线程获取时,JVM会把对象头中标志位设为01,即偏向模式

    2. CAS操作把获得该的锁的线程ID记录在Mark Word中,如果成功则执行同步代码块,如果失败
      则通过CAS竞争锁,成功则执行同步代码块,如果失败则将锁升级为轻量级锁.

  5. 偏向锁撤销

    1. 偏向锁的释放采用了一种只有竞争才会释放锁的机制,线程是不会主动去释放偏向锁,需要等待其他线程来竞争

    2. 当有另一个线程尝试获得该锁,根据所当前的被锁定状态,撤销偏向,恢复到无锁状态01,或轻量级锁状态00

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值