我是李福春,我在准备面试,今天的题目是:
synchronized底层是如何实现的?
答: synchronized是在底层的jvm中实现的,即c++写的,synchronized的实现是基于一对monitorenter, monitorexit指令实现的,monitor对象是同步的基本实现单元。
在java6中,monitor依靠操作系统提供的内部互斥锁,需要在用户态空间和内核态空间切换,所以同步操作是一个比较重的操作,开销比较大。
在java7之后,monitor有三种不同的实现,即偏斜锁,轻量级锁,重量级锁。
基于对象头的markword,标记上偏向的线程id, 在没有竞争的条件下,使用的是偏斜锁;
当有多个线程来竞争偏斜锁,基于cas对对象头的markword来进行竞争,如果拿到了,升级为轻量级锁。
没拿到则升级为重量级锁;
锁降级发生在jvm进入安全点检查的时候,对monitor进行降级。
synchronized底层实现
对象头结构:
sharedRuntime.cpp 解释器和编译器的运行时基类。
Handle h_obj(THREAD, obj); if (UseBiasedLocking) { // Retry fast entry if bias is revoked to avoid unnecessary inflation ObjectSynchronizer::fast_enter(h_obj, lock, true, CHECK); } else { ObjectSynchronizer::slow_enter(h_obj, lock, CHECK); }
偏斜锁逻辑代码:
void ObjectSynchronizer::fast_enter(Handle obj, BasicLock* lock, bool attempt_rebias, TRAPS) { if (UseBiasedLocking) { if (!SafepointSynchronize::is_at_safepoint()) { BiasedLocking::Condition cond = BiasedLocking::revoke_and_rebias(obj, attempt_rebias, THREAD); if (cond == BiasedLocking::BIAS_REVOKED_AND_REBIASED) { return; } } else { assert(!attempt_rebias, "can not rebias toward VM thread"); BiasedLocking::revoke_at_safepoint(obj); } assert(!obj->mark()->has_bias_pattern(), "biases should be revoked by now"); } slow_enter(obj, lock, THREAD); }
轻量级锁:
void ObjectSynchronizer::slow_enter(Handle obj, BasicLock* lock, TRAPS) {
markOop mark = obj->mark();
if (mark->is_neutral()) {
// 将目前的Mark Word复制到Displaced Header上
lock->set_displaced_header(mark);
// 利用CAS设置对象的Mark Word
if (mark == obj()->cas_set_mark((markOop) lock, mark)) {
TEVENT(slow_enter: release stacklock);
return;
}
// 检查存在竞争
} else if (mark->has_locker() &&
THREAD->is_lock_owned((address)mark->locker())) {
// 清除
lock->set_displaced_header(NULL);
return;
}
// 重置Displaced Header
lock->set_displaced_header(markOopDesc::unused_mark());
ObjectSynchronizer::inflate(THREAD,
obj(),
inflate_cause_monitor_enter)->enter(THREAD);
}
java体系中的锁
java提供的锁有哪些
再入读写锁:
public class RWSample { private final Map<String, String> m = new TreeMap<>(); private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock r = rwl.readLock(); private final Lock w = rwl.writeLock(); public String get(String key) { r.lock(); System.out.println("读锁锁定!"); try { return m.get(key); } finally { r.unlock(); } } public String put(String key, String entry) { w.lock(); System.out.println("写锁锁定!"); try { return m.put(key, entry); } finally { w.unlock(); } } // … }
优化的读写锁:StampedLock
代码如下:
读取之前先通过validate方法判断是否进入写状态,如果没有进入写状态,不用加读锁,避免了开销;
否则增加读锁,保证一致性。
public class StampedSample { private final StampedLock sl = new StampedLock(); void mutate() { long stamp = sl.writeLock(); try { write(); } finally { sl.unlockWrite(stamp); } } Data access() { long stamp = sl.tryOptimisticRead(); Data data = read(); if (!sl.validate(stamp)) { stamp = sl.readLock(); try { data = read(); } finally { sl.unlockRead(stamp); } } return data; } // … }
小结
本篇先介绍了synchronized的底层实现原理,介绍了java8中引入的3种级别的锁,以及锁升级和降级过程。
然后介绍了java体系中的其它的锁和优化读写锁使用场景。
原创不易,转载请注明出处,让我们互通有无,共同进步,欢迎沟通交流。
原文
https://segmentfault.com/a/1190000022172167
本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 面试刷题15:synchronized底层是如何实现的?