synchronize总结
官方解释,别人翻译的:
同步方法的运行是隐式的,类似于jvm对于方法的引用和返回的支持。同步方法通过在运行常量池里method_info数据结构中的ACC_SYNCHRONIZED标签来标注。
如果一个线程发现调用的方法有ACC_SYNCHRONIZED标记,那么线程的执行过程就变成:获取monitor对象,调用方法,释放monitor对象。
在某个线程持有monitor对象时,如果其他线程也想获取该对象,则会别阻塞。
如果一个同步方法执行过程中发生异常,而且方法自己没有处理,那么在异常被向外抛时,线程也会自动释放monitor对象。
1.使用方式
a.普通方法,上锁的对象是类实例,反编译后字节码中会有ACC_SYNCHRONIZED关键字
b .静态方法,上锁的对象是类对象,和上面差不多
c.静态代码块,自定义锁的对象,在代码块的前后会有monitorenter、monitorexit关键字,标识计数器+1,或者减1
2.存放方式
synchronized使用的锁对象是存储在Java对象头里的,而对象头结构
其中Mark Word在默认情况下存储着对象的HashCode、分代年龄、锁标记位等以下是32位JVM的Mark Word默认存储结构:
还有如下可能变化的结构:
Synchronized属于结构中的重量级锁,对象的对象头的锁信息里面包含了monitor,每个对象都有一个monitor与之关联,类似一个管家,获取锁本质就是获取monitor
monitor是由ObjectMonitor(c++)实现的,
结构中几个重要的字段要关注,_count、_owner、_EntryList、_WaitSet。
count用来记录线程进入加锁代码的次数。
owner记录当前持有锁的线程,即持有ObjectMonitor对象的线程。
EntryList是想要持有锁的线程的集合。
WaitSet 是加锁对象调用wait()方法后,等待被唤醒的线程的集合。
3.锁的获取逻辑
4.锁升级
5.synchronize原理
6.synchronize和lock
参考:
https://blog.csdn.net/a760352276/article/details/107620307
https://www.cnblogs.com/little-sheep/p/9909111.html 这是厉害