Synchronized实现原理与常见面试题

Synchronized 是常被我们用来保证临界区以及临界资源安全的解决方案。它可以保证当有多个线程访问同一段代码,操作共享数据时,其他线程必须等待正在操作线程完成数据处理后再进行访问。即 Synchronized 可以达到线程互斥访问的目的。

所以,我们可以了解到,Synchronized锁代表的锁机制有如下两种特性:互斥型和可见性。

  • 互斥性:同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程中并发安全;

  • 可见性:确保锁在释放之前所做的操作,对之后的其他线程是可见的(即之后获取到该锁的线程获取到的共享变量是最新的)。

除此之外,JDK 1.6后还对synchronized锁进行了优化,使其摆脱了重量级锁的称号。接下来就来了解以下synchronized的实现以及优化。

一、Synchronized对应的锁对象

理论上Java中所有的对象都可以作为锁,Java中根据synchronized使用的场景不同,其锁对象也是不一样的。可以有以下场景:

场景 具体分类 锁对象 代码示例
修饰方法 实例方法 当前实例对象 public synchronized void method () {
...
}
... 静态方法 当前类的Class对象 public static synchronized void method () {
...
}
修饰代码块 代码块 ( )中配置的对象 synchronized(object) {
...
}

所以,当一个线程要访问一段同步代码块时,它必须获取到如上表中的锁对象。那么这一过程在字节码中又是怎么表示的呢?

二、 Monitor机制与Java对象头

首先我们来看一段小Demo:

 

Copy

public class Demo {

public static void main(String[] args) {
synchronized (Demo.class) { }
method();
}

private static void method() { }
}

图片

可以看到执行同步代码块首先需要去执行monitorenter指令,退出的时候需要执行monitorexit指令。我们来观察monitorenter指令底层的逻辑,其源码如下:

 

Copy

IRT_ENTRY_NO_ASYNC(void, InterpreterRuntime::monitorenter(JavaThread* thread, BasicObjectLock* elem))
#ifdef ASSERT
thread->last_frame().interpreter_frame_verify_monitor(elem);
#endif
if (PrintBiasedLockingStatistics) {
Atomic::inc(BiasedLocking::slow_path_entry_count_addr());
}
Handle h_obj(thread, elem->obj());
assert(Universe::heap()->is_in_reserved_or_null(h_obj()),
"must be N

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值