Synchronized关键字

Java普通对象结构:

Mark Word里面又存储了具体的锁信息:

线程在执行同步块之前,JVM会先在当前线程的栈桢中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中,官方称为Displaced Mark Word

上图为32位JVM中Mark Word(32bit)在不同锁的状态下存储的内容:

无锁时:25bit用于存储对象的HashCode,4bit用于存储分代年龄(4bit,所以最大就15),1bit用于标识是否是偏向锁(此处为0),2bit为锁标志位(01),标志是什么锁

偏向锁:HashCode会变为锁主人的线程信息(23bit)和加锁时间戳(2bit),4bit用于存储分代年龄,1bit用于标识是否是偏向锁(此处为1,和无锁状态区分),2bit为锁标志位(01)

偏向锁的加锁步骤(一个线程访问同步块时):

  • Load-and-test,也就是简单判断一下当前线程id是否与Markword当中的线程id是否一致.
  • 如果一致,则说明此线程已经成功获得了锁,继续执行下面的代码.
  • 如果不一致,则要检查一下对象是否还是可偏向,即“是否偏向锁”标志位的值,即判断值是否为1。
  • 如果还未偏向(即不为1时),则利用CAS操作来竞争锁
  • 若已经偏向(即为1时),则尝试使用CAS将偏向锁指向当前线程

偏向锁---->轻量级锁:需先撤销偏向锁,再加轻量级锁

偏向锁撤锁:

其他线程尝试竞争偏向锁时,持有偏向锁的线程才会释放锁(否则一直持有)

  • 在一个安全点(没有正在执行字节码的时间点)停止拥有锁的线程。
  • 遍历线程栈,如果存在锁记录的话,需要修复锁记录和Markword,使其变成无锁状态。
  • 唤醒当前线程,将当前锁升级成轻量级锁。

轻量级锁的加锁步骤:

  • 线程在自己的栈桢中创建锁记录LockRecord。
  • 将锁对象的对象头中的Mark Word复制到线程的刚刚创建的锁记录中。
  • 将锁对象的对象头的MarkWord替换为指向锁记录的指针
  • 替换成功,则当前线程获取锁
  • 替换失败,当前线程尝试使用自旋(线程会原地循环(消耗CPU)等待,而不是阻塞此线程,直到获取到锁)来获取锁

如果竞争的线程越来越多,锁即变重量级锁,为互斥锁,即为synchronized,锁标志位变位10,Mark Word其余内容被替换为一个指向对象监视器Monitor的指针

升级为重量级锁时,其他线程试图获取锁时,都会被阻塞住,当持有锁的线程释放锁后会唤醒这些线程,进行新一轮的争锁

特殊的是,如果此对象已经被GC标记过(gc标记不一定会被回收),lock会变为11

Monitor对象

每个对象都有一个Monitor对象相关联,Monitor对象中记录了持有锁的线程信息、等待队列等。Monitor对象包含以下三个字段:

  • _owner 记录当前持有锁的线程
  • _EntryList 是一个队列,记录所有阻塞等待锁的线程
  • _WaitSet 也是一个队列,记录调用 wait() 方法并还未被通知的线程

当线程持有锁的时候,线程id等信息会拷贝进owner字段,其余线程会进入阻塞队列entrylist,当持有锁的线程执行wait方法,会立即释放锁进入waitset,当线程释放锁的时候,owner会被置空,公平锁条件下,entrylist中的线程会竞争锁,竞争成功的线程id会写入owner,其余线程继续在entrylist中等待。

Monitor与Synchronized

对于Synchronized的同步代码块,JVM会在进入代码块之前加上monitorenter ,如果进入monitor成功,线程便获取了锁,一个对象的monitor同一时刻只能被一个线程锁占有;

对于同步方法,JVM会讲方法设置 ACC_SYNCHRONIZED 标志,调用的时候 JVM 根据这个标志判断是否是同步方法。

采用Synchronized给对象加锁会使线程阻塞,因而会造成线程状态的切换,而线程状态的切换必须要操作系统来执行,因此需要将用户态切换为内核态,这个切换的过程是十分耗时的都需要操作系统来帮忙,有可能比用户执行代码的时间还要长。

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值