在上一次https://www.cnblogs.com/webor2006/p/11446129.html的理论的最后谈到了锁的演化,如下:
下面具体来阐述一下:
偏向锁:它是针对一个线程来说, 它的主要作用就是优化同一个线程多次获取一个锁的情况;如果一个synchronized方法被一个线程访问,那么这个方法所在的对象就会在其Mark Word中将偏向锁进行标记,同时还会有一个字段来存储该线程的ID;当这个线程再次访问一个synchronized方法时,它会检查这个对象的Mark Word的偏向锁标记以及是否指向了其线程ID,如果是的话,那么该线程就无需再去进入管程(Monitor)了,而是直接进入到该方法体中。
如果是另外一个线程访问这个synchronized方法,那么实际情况会如何呢?偏向锁会被取消掉。
轻量级锁:若第一个线程已经获取到了当前对象的话,这时第二个线程又开始尝试争抢该对象的锁,由于该对象的锁已经被第一个线程获取到,因此它是偏向锁,而第二个线程在争抢时,会发现该对象头中的Mark Word已经是偏向锁,但里面存储的线程ID并不是自己(是第一个线程),那么它会进行CAS(Compare and Swap),从而获取到锁,这里面存在两种情况:
1、获取锁成功:那么它会直接将Mark Word中的线程ID由第一个线程变成自己(偏向锁标记位保持不变),这样该对象依然会保持偏向锁的状态。
2、获取锁失败:则表示这时可能会有多个线程同时在尝试争抢该对象的锁,那么这时偏向锁就会进行升级,升级为轻量级锁。
自旋锁:先回忆一下它的概念:
下面对它进行进一步阐述:
若自旋失败(依然无法获取到锁),那么锁就会转化为重量级锁,在这种情况下,无法获取到锁的线程都会进入到Monitor(既内核态)。自旋最大的一个特点就是避免了线程从用户态进入到内核态。
重量级锁:
线程最终从用户态进入到内核态。