synchronized

jdk1.5之后,先升级为偏向锁,markword记录这个线程id,如果线程争用,则升级自旋锁,默认自旋10次,之后升级为重量级锁,锁只能升级不能降级

synchronized 主要是由monitorenter和monitorexit两个原语来实现同步的,当线程进入Monitorenter获取执行代码的权利时,其他线程就不能执行里面的代码,知道锁owner执行monitor 释放锁后,其他线程才可以竞争锁;

普通方法

常量池中多了ACC_SYNCHRONIZED标示符。JVM就是根据该标示符来实现方法的同步的:当方法调用时会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先获取monitor,获取成功之后才能执行方法体,方法执行完后再释放monitor。在方法执行期间,其他任何线程都无法再获得同一个monitor对象。这种方式与语句块没什么本质区别,都是通过竞争monitor的方式实现的。只不过这种方式是隐式的实现方法。

静态方法

常量池中用ACC_STATIC标志了这是一个静态方法,然后用ACC_SYNCHRONIZED标志位提醒线程去竞争monitor。由于静态方法是属于类级别的方法(即不用创建对象就可以被调用),所以这是一个类级别(XXX.class)的锁,即竞争某个类的monitor

monitor介绍

1.每个对象有一个监视器锁(monitor)。当monitor被占用时就会处于锁定状态,线程执行monitorenter指令时尝试获取monitor的所有权,过程如下:

如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。

2.如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1.这里涉及重入锁,如果一个线程获得了monitor,他可以再获取无数次,进入的时候monito+1,退出-1,直到为0,开可以被其他线程获取

3.如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权

volatile MESI缓存一致性协议,写操作的时候会导致其他cpu的缓存行失效;

T t=new T();  分成三部,  1.首先给对象分配内存,2,然后给对象初始化,3,把初始化后的对象给t,   但是编译器在编译执行的时候可能执行1后,先执行3后执行2,对于其他线程正好在执行完3还没执行2的时候获取t的对象,这个时候t是非Null的

CAS  乐观锁,无锁优化,  源值,新值,内存值(期望值),  ABA问题,基本类型没什么影响,但对于引用对象有影响,比如某个对象的属性经过另外一个线程改变了,虽然引用地址没有变,但是里面的属性值被变动了,如果你要根据这个对象做逻辑判断,肯定就不是你当初的值了

整个juc都是建立在cas上的,是一种系统原语,原语属于操作系统范畴,由若干条指令组成的,也就是说CAS是一条CPU指令,不会造成所谓的系统不一致的问题,所以利用CPU的CAS命令,同时借助JNI来完成的非阻塞算法,因此相对于synchronized 阻塞算法,性能提高很多

Unsafe  

原文地址:https://www.cnblogs.com/lhh-boke/p/13905847.html