美文网首页
Synchronized锁实现浅析

Synchronized锁实现浅析

作者: masterFan | 来源:发表于2018-05-15 22:08 被阅读0次

引言

在多线程并发访问下,如何确保数据的正确性至关重要。最常用的保证线程安全的方式是通过加锁,加锁后多线程并发访问转变成串行访问,这由此也引发了加锁后性能下降,线程切换频繁等问题。那么,究竟Synchronized内部是如何实现同步互斥机制的呢?

Synchronized是什么

在Java并发编程里,线程安全是最最需要关注的问题。那什么是线程安全呢?可以简单的理解为,线程安全就是多线程访问下,能正确的读取和写入共享数据的方式;那么,Synchronized就是为了提供线程安全的一种常用的实现机制。

Synchronized也称为同步互斥的机制,通过在方法中或代码块增加Synchronized关键字,JVM会将多线程并行访问模式转变为串行排队访问模型,保证同一个时间内只有唯一的线程在执行代码和访问共享数据。

Synchronized实现原理

Synchronized底层实现

Synchronized关键字最常用于修饰方法和代码块

// 同步块
synchronized(obj) {...};
// 同步方法
public synchronized void method(){...}

通过对生成的class文件执行javap -verbose命令, 可以看到synchronized的字节码实现


同步块字节码实现 同步方法字节码实现

我们可以看到,同步块是通过分别插入monitorentermonitoreixt俩指令,而同步方法则采用了ACC_SYNCHRONIZED标识位来标示为一个同步方法。这两种同步虽然在表现形式上存在差异,但实现上都是采用Monitor模式来实现的。

Monitor模式

Monitor模式提供了线程间互斥与协同的同步实现机制,互斥执行确保同一时间点内只有一个线程操作共享内存数据,配合wait/notify/notifyAll来协调线程进行有序的工作。

原理图
monitor实现原理

可以看到Monitor分别有三个不同的区域组成,分别是
Entry Set: 进入synchronized,尝试获取monitor对象的线程集合区域。
The Owner:持有monitor对象线程执行的同步Monitor区域。
Wait Set:调用wait方法后,被挂起等待的线程区域。

线程在Monitor模式下状态转变的过程可以分为以下几个步骤
1.enter -- 线程进入Entry Set区域,如果区域内有其他的线程,那么进行排队等待;否则,进入步骤2.
2.acquire in Entry Set -- 线程尝试获取monitor对象,如果线程获取锁成功,进入步骤3;否则,线程将在Entry Set阻塞等待。
3.release and exit -- 若持有monitor对象的线程执行完整段Monitor区域代码后,并且没有执行wait/notify的指令。那么,线程就释放monitor对象,并退出Owner区域。
4.release -- 若持有对象锁的线程执行到wait指令,线程将释放掉占有monitor对象的锁资源,并进入Wait Set区域,进入这个区域的线程将处于休眠状态等待再次被唤醒进入到Owner区域内。
5.acquire in Wait Set -- 当Owner区域中的线程调用了notify/notifyAll方法后,会唤醒单个或所有在Wait Set区域中的线程重新竞争获取monitor锁资源。

注:当执行notify方法时,不当当会引起Wait Set内的线程争抢对象锁;同时争抢对象锁的还包括在Entry Set内等待的线程集合。Wait Set vs Entry Set(线程优先级越高,竞争成功得几率最大),竞争成功得线程,将成为对象锁的持有者,进入Owner区域。

相关文章

网友评论

      本文标题:Synchronized锁实现浅析

      本文链接:https://www.haomeiwen.com/subject/slzsdftx.html