###实现原理
synchronized是通过指令monitorentor 和monitorexit指令实现的
由上图可以看出,线程想要访问对象,是需要监视器(Monitor)配合同步队列(SynchronizedQueue)给对象加锁的。
SynchronizedQueue 同步队列是一个双向链表 FIFO ,也是由CAS原理实现的
为什么使用链表 而不使用数组? 是因为双向链表 可以在新增和删除的时候,各加一个锁,一共2个锁,性能更高。而数组只能加1个锁。
###锁的信息放在哪儿?
synchronized是给对象或类加的锁。
1、对于普通的同步方法,锁的是当前的对象
2、对于静态的同步方法,锁的是当前的类
3、对于同步代码块,锁的是()里的对象。
锁的信息放在对象的头部(head)的markword中
###锁的级别
在Java1.6,doug lea(李狗蛋)对synchronized做了优化
##偏向锁
偏向锁是在对象头部的mark word 中维护了一个线程ID,当该线程再次访问对象获取锁的时候,先根据这个线程ID判断是否是该线程。。
释放锁: 只有在出现锁竞争的情况下才会释放锁。释放的过程:暂停拿到锁的该线程,如果该线程已死亡,设置头部的Mark Word为无锁的状态
缺点:如果线程之间存在锁竞争,会带来额外的锁撤销的消耗。适合于只有1个线程访问同步块的场景
关闭偏向锁:可以通过JVM关闭偏向锁:-XX:-UseBiasedLocking=false;
程序会默认进入轻量级锁的状态。
##轻量级锁
轻量级锁也叫乐观锁,是通过cas原理实现的。
#什么是CAS
顾名思义:compare and swap(比较并替换)
老数据:A 期待值: B 写入:V
通过unsafe类中的JNI(Java本地方法,C++)自旋(死循环),不断的判断A 是否等于 B ,假如相等:那么写入V
释放锁:会用CAS将Mark Word的锁状态标记为无锁,如果成功,则释放。如果失败,则表示存在竞争。这时,锁就会膨胀为重量级锁
缺点:不断的自旋消耗CPU的性能
##重量级锁
为总线锁。锁的粒度大,同一时刻,只有1个CPU能访问主内存。
缺点:性能低下。