synchronized锁进阶

1.synchronized锁进阶


1.1 使用场景


修饰普通方法:锁对象是当前实例对象

修饰静态方法:锁对象是当前的类对象

修饰代码块:看括号里面写了啥就是啥


1.2 实现原理


1、java对象的对象头

一个对象在堆内存中的结构如下图,其中对象头中包含:MarkWord和Klass Point(指向类元数据)

 

对象头中的MarkWord:

 

2、monitor锁对象由ObjectMonitor对象实现(c++),数据结构如下:

 

3、竞争锁时,线程状态间的转换

 

①当多个线程同时访问该方法,那么这些线程会先被放进_EntryList队列,此时线程处于blocking状态

②当一个线程获取到了实例对象的监视器(monitor)锁,那么就可以进入running状态,执行方法,此时,ObjectMonitor对象的owner指向当前线程,count加1表示当前对象锁被一个线程获取

③当running状态的线程调用wait()方法,那么当前线程释放monitor对象,进入waiting状态,ObjectMonitor对象的owner变为null,count减1,同时线程进入WaitSet队列,直到有线程调用notify()方法唤醒该线程,则该线程重新获取monitor对象进入Owner区

④如果当前线程执行完毕,那么也释放monitor对象,进入waiting状态,ObjectMonitor对象的owner变为null,count减1

4、修饰代码块和修饰方法,都是基于进入和退出monitor对象来实现的,具体实现却有很大区别:

代码块:

 

方法:

 


1.3 synchronized锁优化升级


1、无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态(级别从低到高)

偏向锁:java6后引进,大多数情况,锁的竞争不激烈,锁总是由同一线程多次获取,为了减少线程获取锁(设计CAS操作,耗时)引入偏向锁。(单个线程执行场景)

轻量级锁:1.6加入,T1执行时,大部分时间没有竞争,少量竞争可以通过cas来解决(线程交替执行场景)

 

重量级锁:线程会放弃cpu执行权,涉及内核态用户态转换(线程竞争激烈场景)

 

2、锁升级

  • 线程T1先判断锁标志位为01,偏向锁0,则将前54位设置为指向自己的指针;

  • 此时T2尝试获得锁,如果T1刚好执行完,则直接向偏向锁指针指向T2;如果T1没有执行完,则向虚拟机申请将偏向锁升级为轻量级锁,申请成功后,T1和T2会将对象头的MarkWord复制一份到自己的栈空间(Lock Record),然后分别用CAS把对象头中的指针指向本线程存储锁记录的地址(Lock Record),比如此时T1成功了(T1将之前的时间片执行完后,再cas,虚拟机裁决此时T1,T2谁CAS成败),则T2的cas失败,T2就会尝试指定次数的自旋来等待T1释放锁。

  • 如果T2超过自旋次数,T1还没有释放锁,则T2懒得自旋了,跟虚拟机申请, 将轻量级锁升级为重量级锁,此时的MarkWord中指针指向的是ObjectMonitor,T2自己(底层调用pthread.mutex_lock)去挂起在_waitSet队列里,T1执行完后发现MarkWord都变了(不指向自己栈上的LockRecord了,那肯定是升级成重量级了),于是释放锁+去唤醒_waitSet队列里的线程。

3、锁粗化

StringBuffer stb = new StringBuffer()//append方法是同步方法
public void test(){
    stb.append("1");//按道理是每个方法都要加同步块,共4个,但是jvm优化后,会把这4个合成一个同步块
    stb.append("1");
    stb.append("1");
    stb.append("1");
}

4、锁消除

public void test2(){
    synchronized (new Object()){//这种无意义的加锁就会被jvm优化消除       
    }
}

参考:https://blog.csdn.net/tongdanping/article/details/79647337

           图灵高并发专题

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值