王有志,一个分享硬核Java技术的互金摸鱼侠
加入Java人的提桶跑路群:共同富裕的Java人
今天是《面霸的自我修养》的第3弹,内容是Java并发编程中至关重要的关键字synchronized,作为面试中的“必考题”,这部分是你必须要充分准备的内容,接下来我们就一起一探究竟吧。
数据来源:
- 大部分来自于各机构(Java之父,Java继父,某灵,某泡,某客)以及各博主整理文档;
- 小部分来自于我以及身边朋友的实际经历,题目上通过🔥来标识,并注明公司。
叠“BUFF”:
- 八股文通常出现在面试的第一二轮,是“敲门砖”,但仅仅掌握八股文并不能帮助你拿下Offer;
- 由于本人水平有限,文中难免出现错误,还请大家以批评指正为主,尽量不要喷~~
- 本文及历史文章已经完成PDF文档的制作,提取关键字【面霸的自我修养】。
应用篇
🔥synchronized是什么?有什么作用(如何保证可见性,如何保证原子性)?
:::info
难易程度:🔥🔥🔥
:::
:::warning
重要程度:🔥🔥🔥🔥🔥
:::
:::success
公司:美团,瑞幸
:::
synchronized是Java提供的关键字,提供了原生同步机制,实现了互斥语义,保证了可见性,有序性和原子性。
有序性和原子性保证是互斥语义带来的,实现互斥的临界区,同一时间仅有一个线程可以执行,所以此时不存在有序性(编译器保证的as-if-serial语义)和原子性问题。
可见性保证是在退出synchronized时,使用了storeload内存屏障,ObjectMonitor::exit
的源码如下:
void ObjectMonitor::exit(bool not_suspended, TRAPS) {
for (;;) {
if (Knob_ExitPolicy == 0) {
OrderAccess::release_store(&_owner, (void*)NULL);
OrderAccess::storeload();
} else {
OrderAccess::release_store(&_owner, (void*)NULL);
OrderAccess::storeload();
}
}
}
storeload指令的执行顺序:
store1;
storeLoad;
load2;
保证load指令要“看”到store指令的最新值,因此store指令后,会将数据写回主内存,同时失效其它处理器中的数据。
🔥synchronized有哪些使用场景?编译后有什么区别?
:::info
难易程度:🔥🔥🔥
:::
:::warning
重要程度:🔥🔥🔥🔥🔥
:::
:::success
公司:字节跳动,蚂蚁金服
:::
synchronized可以用于修饰方法,或者代码块。
修饰方法时,编译后会添加ACC_SYNCHRONIZED
标识,指明该方法是同步方法,JVM通过ACC_SYNCHRONIZED
标识来判断是否执行同步调用。
public synchronized void method();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
修饰代码块时,编译后在代码块开始和结束位置分别添加monitorenter
和monitorexit
指令,执行monitorenter
时获取锁,执行monitorexit
指令时释放锁。
public void method();
descriptor: ()V
flags: ACC_PUBLIC
Code:
......
4: monitorenter
....