第二章:四、偏向锁的原理与实战
2023-11-02 17:30 阿方技术圈 阅读(101) 评论(0) 收藏 举报偏向锁主要解决无竞争下的锁性能问题,所谓的偏向就是偏心,即锁会偏向于当前已经占有锁的线程。
偏向锁的核心原理
在实际场景中,如果一个同步块(或方法)没有多个线程竞争,而且总是由同一个线程多次重入获取锁,如果每次还有阻塞线程,唤醒CPU从用户态转为核心态,那么对于CPU是一种资源的浪费,为了解决这类问题,就引入了偏向锁的概念。
偏向锁的核心原理是:如果不存在线程竞争的一个线程获得了锁,那么锁就进入偏向状态,此时Mark Word的结构变为偏向锁结构,锁对象的锁标志位(lock)被改为01,偏向标志位(biased_lock)被改为1,然后线程的ID记录在锁对象的Mark Word中(使用CAS操作完成)。以后该线程获取锁时判断一下线程ID和标志位,就可以直接进入同步块,连CAS操作都不需要,这样就省去了大量有关锁申请的操作,从而也就提升了程序的性能。
偏向锁的主要作用是消除无竞争情况下的同步原语,进一步提升程序性能,所以,在没有锁竞争的场合,偏向锁有很好的优化效果。但是,一旦有第二条线程需要竞争锁,那么偏向模式立即结束,进入轻量级锁的状态。
假如在大部分情况下同步块是没有竞争的,那么可以通过偏向来提高性能。即在无竞争时,之前获得锁的线程再次获得锁时会判断偏向锁的线程ID是否指向自己,如果是,那么该线程将不用再次获得锁,直接就可以进入同步块;如果未指向当前线程,当前线程就会采用CAS操作将Mark Word中的线程ID设置为当前线程ID,如果CAS操作成功,那么获取偏向锁成功,执行同步代码块,如果CAS操作失败,那么表示有竞争,抢锁线程被挂起,撤销占锁线程的偏向锁,然后将偏向锁膨胀为轻量级锁。偏向锁的缺点:如果锁对象时常被多个线程竞争,偏向锁就是多余的,并且其撤销的过程会带来一些性能开销。
public class BiasedLockTest {
int a=1;
double b=1.1;
public static void main(String[] arg){
System.out.println(VM.current().details());
Person person=new Person();
ClassLayout layout=ClassLayout.parseInstance(person);
new Thread(()->{
System.out.println("获取偏向锁前:");
System.out.println(layout.toPrintable());
synchronized (person) {
System.out.println("获取偏向锁中:");
System.out.println(layout.toPrintable());
}
System.out.println("获取偏向锁结束后:");
System.out.println(layout.toPrintable());
}
,"thread1").start();
}
private static class Person {
}
浙公网安备 33010602011771号