JAVA并发之synchronized

2020-07-02  本文已影响0人  小软_GCX

synchronized

synchronized

首先synchronized是jdk提供的内置锁,既然是锁那就具有互斥性和可见性,可保证在多线程竞争资源时不会出现并发问题

synchronized用法

根据修饰对象分类

根据获取的锁分类

​ 在 Java 中,每个对象都会有一个 monitor 对象,这个对象其实就是 Java 对象的锁 ,因为类对象本来也是一个对象,所以每个类也有一个类锁。

​ 当某一线程占有这个monitor对象的时候,先看monitor计数器是不是0,如果是0,说明还没有线程占用,这时候该线程占有这个锁,并且计数器+1;如果计数器不是0,看当前占有锁的线程是不是本线程,如果是本线程就+1,这就是可重入的概念;如果当前计数器不是0也不是当前线程占有,则进去阻塞状态。

synchronized原理分析

代码块加锁的实现是通过monitorEnter 和monitorExit来实现的,通过javap 反编译class文件你会发现synchronized所包含的代码前面和后面分别加了monitorEnter 和monitorExit,其中有两个monitorExit,第一个是正常解锁时执行的,第二个是异常时用来释放锁的。

image.png

对方法加锁的实现是通过标志位ACC_SYNCHRONIZED来实现的

image.png

JAVA虚拟机对synchronized的优化

在jdk1.6以前synchronized是一个重量级锁,1.6及以后将它优化为无锁,偏向锁,轻量级锁,重量级锁

偏向锁: 在对象第一次被某一线程占有的时候 ,将线程号写入,下一个线程再次访问时,发现线程号是当前占用线程号,直接成功,否则升级为轻量级锁

轻量级锁:是一个自旋锁,通过cas自旋来获取锁,超过一定次数升级为重量级锁

重量级锁:通过互斥量来实现,性能比较低

synchronized是一个非公平锁

moniter 对象中有两个集合 _EntryList, _WaitSet 当线程阻塞的时阻塞线程会进入_EntryList,等待count为0重新调用,当线程调用了wait方法是线程会阻塞进入_WaitSet中 等待notify唤醒 ,无论是哪种情况 当一个新的线程进来同时count 为0 是 都不能保证新的线程在_EntryList或者_WaitSet 中先执行其中线程

上一篇下一篇

猜你喜欢

热点阅读