synchronized实现原理
来源gao@daima#com搞(%代@#码网
synchronized是java提供用于解决线程原子性操作相干问题的内置锁。对于每个对象来说,都有一个monitor,你能够把它看做是一个同步工具,synchronized须要通过操作monitor来实现锁的获取和开释。
当synchronized作用于对象的时候,反编译能够看到2个指令,monitorenter和monitorexit
当而synchronized作用于办法的时候,则是在标识符flags里增加一个ACC\_SYNCHRONIZED标记,来实现同步性能
当线程执行到monitorenter指令时,会去尝试获取monitor,如果锁计数器为0,就会将计数器+1,其余线程就无奈获取以后对象的monitor,没有获取到monitor的线程将会阻塞。如果再次重入monitor,计数器会持续+1。相同的,执行monitorexit指令时,会将计数器-1,直到计数器为0的时候,以后线程会开释monitor。
那么,monitor又是如何工作的呢
进一步细化,对于monitor来说,有2个队列entryList和waitSet,线程在申请获取monitor之前都会进入entryList
1.当有一个线程获取到monitor之后会进入一个Owner区域,同时对计数器进行+1,此时对于entryList里的线程来说都是阻塞的,期待锁开释。
2.进入Owner的线程调用wait办法,会开释monitor,同时计数器-1,并进入waitSet队列期待被唤醒,entryList内的线程开始新一轮的竞争
3.有线程调用notify办法的时候,waitSet内的某个线程会被唤醒(当然,如果调用notifyAll会唤醒所有wait线程),线程会从新进入entryList,去持续下一轮竞争
4.执行完同步代码的线程会退出区域,同时开释锁
monitor与对象关联
一个对象次要由三局部组成
对象头:包含Mark Word和Class Pointer
实例数据:存储对象理论无效信息,类属性数据信息等
对齐填充:虚拟机要求对象的起始地址必须是8字节的整数倍,对齐填充相当于占位符的作用
对象头中的Class Pointer是指向对象类元数据的指针,由此获取对象是哪个类的实例
对象头的Mark Word次要存储对象的运行时数据,包含hashcode,分代年龄,GC标记,是否偏差锁,偏差锁线程ID,轻量级锁指针,重量级锁指针等信息,对于synchronize来说,属于重量级锁,所以重量级锁指针就指向monitor的地址。
Mark Word引出了一些锁的概念,比方偏差锁,轻量级锁,重量级锁,之后更新一期对于锁的分配机制和优化机制的文章,看一看jvm是如何优化内置锁的