synchronized关键字底层原理

synchronized底层的原理,跟jvm指令和monitor有关系

如果用到了synchronized关键字,在底层编译后的jvm指令中,会有monitorenter和monitorexit两个指令

monitorenter

// 代码对应的指令

monitorexit

每个对象都会关联一个monitor,比如一个对象实例就有一个monitor,一个类的Class对象也有一个monitor,如果要对这个对象加锁,那么必须获取这个对象关联的monitor的lock锁

 

monitor里会有一个计数器,从0开始,如果一个线程想要获取monitor锁,看它的计数器是否为0,如果为0,那么说明锁空闲,它就可以获取锁了,然后计数器加1

另外monitor的锁是支持重入加锁的

 

synchronized(myLock){ (1)

       // 代码

       synchronized(myLock){ (2)

           //代码

       }

}

如果一个线程第一次执行到synchronized (1) 那里,会获取到myLock对象的monitor的锁,计数器会加1,然后第二次执行synchronized (2) 那里,会再次获取到myLock对象的monitor的锁,这个就是重入锁,然后计数器会再次加1,变成 2

 

这个时候如果其它线程,第一次执行到synchronized那里,会发现myLock对象的monitor锁的计数器是大于0的,意味着被别的线程加锁了,然后此时线程会进入block阻塞状态,等待获取锁。

 

解锁流程

synchronized(myLock){ (1)

       // 代码

       synchronized(myLock){ (2)

           //代码

       } // 解锁 计数器减1

} // 解锁 计数器减1

synchronized关键字可以同时保证原子性,可见性和有序性

原子性:原子性层面而言,有一个加锁和释放锁的机制,加锁之后,同一段代码只有自己可以执行,通过ObjectMonitor

可见性:可见性会通过加入一些内存屏障,在同步代码块对变量做的写操作,都会在释放锁的时候,全部执行flush操作,在进入同步代码块的时候,对变量的读操作,全部会强制执行refresh操作

有序性:有序性会通过各种各样的内存屏障,来解决LoadLoad,StoreStore,StoreLoad,LoadStore等等重排序,通过Acquire屏障和Release屏障,保证同步代码块内部的指令和外部的指令不能重排,Acquire就是LoadLoad和LoadStore屏障,Release就是StoreLoad和StoreStore屏障

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值