synchronized 关键字的使用及底层原理

synchronized是Java中的关键字,用于保证多线程环境下的数据一致性。它可以修饰实例方法、静态方法或代码块,基于对象监视器monitor实现锁机制。在JDK1.6后,官方对其进行了优化,包括自旋锁、偏向锁和轻量级锁等,提高了锁的性能。
摘要由CSDN通过智能技术生成

一、什么是synchronized 关键字

synchronized 关键字可以保证被它修饰的方法或者代码块在任意时刻只有一个线程能够执行。

二、怎么使用 synchronized 关键字

  • 修饰实例方法时,获取的是当前对象实例的锁
synchronized void method() {
    //业务代码
}
  • 修饰静态方法时,获取的是当前类Class的锁,因为静态方法不属于任何一个实例对象(不管new了多少个对象,都只有一份)。这里有点区别于修饰实例方法。
synchronized static void method() {
    //业务代码
}
  • 修饰代码块时,需要指定锁对象synchronized(this|object)
synchronized(this) {
    //业务代码
}

三、synchronized 关键字的底层原理

1、新建Demo类,synchronized 修饰了制定代码块

public class SynchronizedDemo {
    public void method() {
        synchronized (this) {
            System.out.println("synchronized 代码块");
        }
    }
}

2、执行javap -c -s -v -l SynchronizedDemo.class,查看底层字节码。

在这里插入图片描述

synchronized 同步代码块使用的是 monitorentermonitorexit 指令,monitorenter 指向同步代码块开始位置,monitorexit 指向同步代码块结束位置(图中可以看到第19行还有一个monitorexit的原因,是处理程序出现异常的时候执行这个monitorexit来退出锁,如果程序没有异常直接在14行go to至22行就直接return了)。

synchronized 锁本质就是对对象监视器 monitor 的获取。

在执行monitorenter时,会尝试获取对象的锁,如果锁的计数器为 0 则表示锁可以被获取,获取后将锁计数器设为 1 也就是加 1。如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。

在这里插入图片描述

对象锁的的拥有者线程才可以执行 monitorexit 指令来释放锁。在执行 monitorexit 指令后,将锁计数器设为 0,表明锁被释放,其他线程可以尝试获取锁。

在这里插入图片描述

四、JDK1.6 之后对 synchronized 关键字的优化

在 Java 早期版本中,synchronized 属于 重量级锁,效率低下,庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对 synchronized 较大优化,所以现在的 synchronized 锁效率也优化得很不错了。

JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值