Java并发之synchronized关键字

本文详细解析了Java中的synchronized关键字,包括其使用方式、底层原理、特点及适用场景。介绍了synchronized如何实现对象级锁,以及其在方法级的隐式锁机制。强调了synchronized的可重入特性,并指出在并发量较低的情况下,使用synchronized是较为合适的选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java并发之synchronized关键字

    synchronized是Java的重量级锁,本文将从synchronized的使用方式,底层原理,特点和适用场景讲解。让你彻彻底底明白Java中的synchronized。

01

使用方式

 

    先来看一下synchronized关键字的同步基础:Java中的每一个对象都可以作为锁。为什么对象可以作为锁呢?这里暂时先不讨论。来看一看synchronized的使用方式:

     1.对于普通同步方法,锁是当前实例对象

     2.对于静态同步方法,锁是当前类的Class对象

     3.对于同步方法块,锁是Synchronized括号内配置的对象。

02

底层原理

    先从同步方法块开始说synchronized的底层原理。有可能你写出下面的代码

public class Test{
  private Object lock=new Object();
  public void test1()
  {
    synchronized(lock)
    {
      //do something
    }
  }
}

    生成Class文件后,使用javap对class文件进行反编译,省略部分无用的细节后,可以看到如下

 public void test1();
    Code:
       0: aload_0
       1: getfield      #3 // Field lock:Ljava/lang/Object;
       4: dup
       5: astore_1
       6: monitorenter
       7: aload_1
       8: monitorexit
       9: goto          17
      12: astore_2
      13: aload_1
      14: monitorexit
      15: aload_2
      16: athrow
      17: return

     可以看到monitorenter和monitorexit指令。其实,同步代码块是使用这两种指令实现的。任何对象都有一个monitor与之关联,当且一个monitor被持有之后,它将处于锁定状态。线程执行到monitorenter指令时,将会尝试获取对象所对应的monitor的所有权,即尝试获取对象的锁。

    与同步代码块不同的是,方法级的同步是隐式的,即无须通过字节码指令来控制,它实现在方法调用和返回操作中。虚拟机可以从方法常量池中的ACC_SYNCHRONIZED访问标志得知方法是否声明为同步方法。换句话说,如果方法是synchronized方法,那么这个标志将会被设置,表示持有了Monitor,方法执行完成后将会释放Monitor。

03

synchronized特点

    需要注意的是,synchronized重量锁是可重入的。什么是可重入呢?也就是持有的锁不会被自己锁死,可以反复持有。我们这里可以递归调用自己的方法:

public class ClassTest {
    public synchronized int  test(int i)
    {
        if(i==0) return 1;
        return i*test(i-1);
    }
    public  static  void  main(String[] args) {
        ClassTest classTest=new ClassTest();
        System.out.println(classTest.test(10));
    }
}

    反复递归调用,计算10的阶乘得到的结果是:

    image.png

    可以看出,synchronized不会被自己锁死。当然,如果方法内部出现异常,当抛出异常时,将释放锁。

04

适用场景

    当并发量比较少时,适用synchronized是一个不错的选择;但是如果并发量较高时,性能严重下降。如果要求内部代码抛出异常后必须释放锁,synchronized可以担当大任。

05

总结

    synchronized要点有:

        1.可以修饰方法,如果是普通方法那么持有对象是当前实例;如果是static方法,则是该类的Class对象,实现机制是ACC_SYNCHRONIZED。

        2.使用同步代码块,那么是括号内配置的对象。底层实现是Monitor,通过monitorenter和monitorexit.

     synchronized是可重入锁,当修饰的代码内部抛出异常时释放持有的锁。

往期精彩回顾

JVM运行时数据区域

Java并发之volatile关键字

死磕Java之JDK 1.6HashMap

2019_02_22_1933083452.png

点击上方蓝色字体,关注我们

15

好看你就点点我

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值