美文网首页
Java synchronized关键字详解

Java synchronized关键字详解

作者: 代码的搬运工 | 来源:发表于2022-04-01 09:15 被阅读0次

    在Java中,线程同步使用最多的方法是使用synchronized关键字。每个Java对象都隐含有一把锁,这里称为Java内置锁(或者对象锁、隐式锁)。使用synchronized(syncObject)调用相当于获取syncObject的内置锁,所以可以使用内置锁对临界区代码段进行排他性保护。

    临界区资源表示一种可以被多个线程使用的公共资源或共享资源,但是每一次只能有一个线程使用它。一旦临界区资源被占用,想使用该资源的其他线程则必须等待。

    临界区代码段是每个线程种访问临界区资源的那段代码,多个线程必须互斥地对临界区资源进行访问。线程进入临界区代码段之前,必须申请资源,申请成功之后执行临界区代码段,执行完成之后释放资源。

    竞态条件可能是由于在访问临界区代码段时没有互斥地访问而导致的特殊情况。如果多个线程在临界区代码段的并发执行结果可能因为代码的执行顺序不同而不同,我们就说这时在临界区出现了竞态条件问题。

    1、synchronized同步方法

    synchronized关键字是Java的保留字,当使用synchronized关键字修饰一个方法的时候,该方法被声明为同步方法。关键字synchronized的位置处于同步方法的返回类型之前。具体的例子如下:

    在方法声明中设置synchronized关键字,保证其方法的代码执行流程是排他性的。任何时间只允许一个线程进入同步方法(临界区代码段),如果其他线程需要执行同一个方法,那么只能等待和排队。

    2、synchronized同步块

    对于小的临界区代码段,我们直接在方法声明中设置synchronized关键字,可以避免竞态条件的问题。但是对于较大的临界区代码段,为了执行效率,最好将其分为多个小的临界区代码段,称为同步块,synchronized同步块的写法如下:

    具体示例如下:

    synchronized方法和synchronized同步块有什么区别呢?总体来说,synchronized方法是一种粗粒度的并发控制,某一时刻只能有一个线程执行该synchronized方法;而synchronized代码块是一种细粒度的并发控制,处于synchronized块之外的其他代码是可以被多个线程并发访问的。在一个方法中,并不一定所有代码都是临界区代码段,可能只有几行代码会涉及线程同步问题。所以synchronized代码块比synchronized方法更加细粒度地控制了多个线程的同步访问。

    synchronized方法和synchronized代码块有什么联系呢?在Java的内部实现上,synchronized方法实际上等同于用一个synchronized代码块,这个代码块包含同步方法中的所有语句,然后在synchronized代码块的括号中传入this关键字,使用this对象锁作为进入临界区的同步锁。

    3、静态的同步方法

    Java有两种对象:Object实例对象和Class对象。

    Object实例对象的方法添加synchronized关键字,其同步锁是当前对象this的对象锁。

    静态方法属于Class对象而不是单个Object实例对象,在静态方法内部是不可以访问Object实例对象的this引用(也叫指针、句柄)的。所以,修饰static方法的synchronized关键字就没有办法获得Object实例的this对象的对象锁。使用synchronized关键字修饰static方法时,synchronized的同步锁并不是Object实例的this对象的对象锁,而是类所对应的Class对象的对象锁。

    类的对象实例可以有很多,但是每个类只有一个Class对象,因此使用Class对象的对象锁作为synchronized的同步锁时会造成同一个JVM内的所有线程只能互斥地进入临界区段。使用synchronized关键字修饰static方法是非常粗粒度的同步机制。

    相关文章

      网友评论

          本文标题:Java synchronized关键字详解

          本文链接:https://www.haomeiwen.com/subject/xhagjrtx.html