java synchronize - 线程同步原理

栏目: Java · 发布时间: 6年前

内容简介:Java支持同步机制的是Monitor支持两种同步机制:wait-notify又可以称作’Singal-continue’。当线程获得 notify,这就是一个信号,线程开始拥有 monitor的所有权,能够 继续 执行 monitor region。执行完之后,此线程释放monitor,一个等待的线程则会获得一样的机会

Java支持同步机制的是 Monitor 。Monitor就像是拥有一个特殊房间的建筑,在同一时间里,这间特殊的房间只能被一个线程拥有。

  • enter the monitor:进入这幢建筑
  • acquiring the monitor:进入建筑里的特殊房间
  • owning the monitor:拥有特殊房间的所有权
  • releasing the monitor:离开特殊的房间
  • exiting the monitor:离开这幢建筑

Monitor支持两种同步机制:

  • 互斥:通过对象锁,使得多线程处理能互相独立的处理共享数据,而不会发生线程不安全
  • 协作:通过对象的wait和notify方法实现,比如一个读的线程从缓冲区读数据,另一个线程负责往缓冲区写数据,如果缓冲区没有数据,则读线程阻塞,有数据时,读线程就要开始消费

wait-notify又可以称作’Singal-continue’。当线程获得 notify,这就是一个信号,线程开始拥有 monitor的所有权,能够 继续 执行 monitor region。执行完之后,此线程释放monitor,一个等待的线程则会获得一样的机会

Monitor的模型如下:

java synchronize - 线程同步原理
1 表示线程刚到达 monitor region ,即 enter the monitor
2 表示线程获取 monitor的所有权,即 acquiring the monitor
3 表示线程执行了 wait,交出所有权,即 releasing the monitor

4 表示原来拥有 monitor 的线程执行了 notify ,恰好被这个线程获取所有权

5 表示线程执行完了 monitor region,即 exiting the monitor

Monitor特意把等待的线程分成了两个部分,Entry Set和Wait Set,Entry Set表示线程刚执行到 Monitor region,而Wait Set则是由于线程执行了wait方法而进入的区域。注意到Object的 notify 以及 notifyAll 要唤醒的对象就处于 Wait Set,换句话说,如果退出 monitor 的线程没有执行 notify/notifyAll ,那么只有 Entry Set 能够获取执行的权限 。如果执行了,则Entry Set和Wait Set中所有的线程都会竞争谁最终能够获取 monitor 的能力

一个线程要离开Wait Set,要么是原拥有 monitor 的线程执行了 notify/notifyAll,要么是wait的时间到了,JVM 会触发一个notify

对象锁

Java能够共享的数据包括两部分:

  • 实例对象:存储在堆中
  • 类实例:存储在方法区,当锁一个类的时候,实际上就是锁类的 Class 对象 对于局部变量,他们存储在栈中,属于线程私有,不会存在共享一说。
    单个线程可以同时锁住一个对象多次,JVM会记住锁住的总次数,每一次释放锁,总次数减一,只有在这个次数变成0的时候,这个锁才有可能被其它线程持有

monitor region 标识的方式

  • 同步代码块
  • 同步方法 JVM使用的指令为
  • monitorenter 获取引用对象的锁
  • monitorexit 是否在monitorenter处获得的对象锁

同步代码块

public class SynchronizedTest {
    private  int i=0;
    public void syn(){
        synchronized (this){
            i++;
        }
    }
}

复制代码

javap -c SynchronizedTest.class 执行后对应的指令如下

public class main.lockTest.SynchronizedTest {
  public main.lockTest.SynchronizedTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iconst_0
       6: putfield      #2                  // Field i:I
       9: return

  public void syn();
    Code:
       0: aload_0    // aload_0 属于 aload_<n> 系列指令的一种。表示获取一个本地变量的引用,然后放入栈中
       1: dup        //弹出栈顶的单字节,然后入栈两次,相当于拷贝了栈顶元素
       2: astore_1        // astore_<n>系列指令的一种。从栈顶获取对象的引用,并存入本地变量
       3: monitorenter      //获取引用对象的锁
       4: aload_0
       5: dup
       6: getfield      #2                  // Field i:I  从栈中获取对象的引用,然后得到它的值
       9: iconst_1        // iconst_<n> 的一种,将常量放入栈中
      10: iadd            // 从操作栈中弹出两个integer,把他们相加,然后将结果重新存入栈中
      11: putfield      #2                  // Field i:I  将值存入引用对象
      14: aload_1
      15: monitorexit    // 释放引用对象的锁
      16: goto          24 // 跳转到下一个指令的位置
      19: astore_2
      20: aload_1
      21: monitorexit
      22: aload_2
      23: athrow    //从操作栈中删掉对象的引用,并抛出这个对象的异常
      24: return     //执行返回
    Exception table:
       from    to  target type
           4    16    19   any
          19    22    19   any
}
复制代码

注意到,如果抛出了异常,也会执行 monitorexit 。印证了无论如何,只要离开了monitor region,锁都会被释放

同步方法

public class SynchronizedTest {
    private  int i=0;
    public synchronized void syn(int i){
            i++;
    }
}

复制代码

对应指令如下

public class main.lockTest.SynchronizedTest {
  public main.lockTest.SynchronizedTest();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iconst_0
       6: putfield      #2                  // Field i:I
       9: return

  public synchronized void syn(int);
    Code:
       0: iinc          1, 1
       3: return
}
复制代码

可以看到两个区别

  1. 在方法上使用 synchronized 没有用到 monitorenter / monitorexit 指令。这是因为在方法上使用synchronized并不需要一个本地变量槽(slot)来存储锁对象
  2. 方法上使用没有创建一个 异常表

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Understanding Machine Learning

Understanding Machine Learning

Shai Shalev-Shwartz、Shai Ben-David / Cambridge University Press / 2014 / USD 48.51

Machine learning is one of the fastest growing areas of computer science, with far-reaching applications. The aim of this textbook is to introduce machine learning, and the algorithmic paradigms it of......一起来看看 《Understanding Machine Learning》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

随机密码生成器
随机密码生成器

多种字符组合密码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试