java synchronized实现可见性过程解析

 更新时间:2019年09月20日 10:54:42   作者:仅此而已-远方  
这篇文章主要介绍了java synchronized实现可见性过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

JMM关于synchronized的两条规定:

1)线程解锁前,必须把共享变量的最新值刷新到主内存中

2)线程加锁时,将清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新获取最新的值

(注意:加锁与解锁需要是同一把锁)

通过以上两点,可以看到synchronized能够实现可见性。同时,由于synchronized具有同步锁,所以它也具有原子性

多线程中程序交错执行时,重排序可能会造成内存可见性问题

接下来我们看一段代码:

/**
 * synchronized能够实现原子性(同步)、可见性
 * 
 * @author xuwenjin
 */
public class SynchronizedDemo {
  //共享变量
  private boolean ready = false;
  private int result = 0;
  private int number = 1;
  /**
   * 写操作
   */
  public void write() {
    ready = true; //1.1
    number = 2;  //1.2
  }
  /**
   * 读操作
   */
  public void read() {
    if (ready) {       //2.1
      result = number * 3; //2.2
    }
    System.out.println("result:" + result);
  }
  //内部线程类
  private class WriteReadThread extends Thread {
    
    private boolean flag = false;    
    public WriteReadThread(boolean flag){
      this.flag = flag;
    }    
    @Override
    public void run() {
      if (flag) {
        write();
      }else {
        read();
      }
    }
  }
  public static void main(String[] args) {
    SynchronizedDemo demo = new SynchronizedDemo();
    //启动线程执行写操作
    demo.new WriteReadThread(true).start();
    //启动线程执行读操作
    demo.new WriteReadThread(false).start();
  }
}

上面的代码可能出现如下执行顺序:

  1) 1.1 --> 1.2 --> 2.1--> 2.2 result的值为6 (正常情况)

  2) 1.1 --> 2.1 --> 2.2 --> 1.2 result的值为3 (当写线程执行完1.1之后,读线程开始)

  3) 1.2 --> 2.1 --> 2.2 --> 1.1 result的值为0 (1.1跟1.2重排序)

  4)...

当然由于重排序和线程的交叉执行,还可能出现很多种执行顺序

导致共享变量在线程间不可见的原因:

  •   a、线程的线程执行
  •   b、重排序结合线程交叉执行
  •   c、共享变量更新后的值没有在工作内存与主内存间及时更新

那么如何解决可见性的问题呢?接下来我们的主角出场:synchronized

安全的代码:

/**
   * 写操作
   */
  public synchronized void write() {
    ready = true; //1.1
    number = 2;  //1.2
  }
  /**
   * 读操作
   */
  public synchronized void read() {
    if (ready) {       //2.1
      result = number * 3; //2.2
    }
    System.out.println("result:" + result);
  }

由于synchronized的原子性、可见性,可以完美解决以上说的三点问题。不过读线程和写线程的执行顺序是不定的,所以result的结果仍然会出现6或0。

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

相关文章

  • Java的回调机制实例详解

    Java的回调机制实例详解

    这篇文章主要介绍了Java的回调机制,结合实例形式详细分析了java回调机制相关原理、用法及操作注意事项,需要的朋友可以参考下
    2019-08-08
  • maven插件maven-assembly-plugin打包归纳文件zip/tar使用

    maven插件maven-assembly-plugin打包归纳文件zip/tar使用

    java项目运行的文件需要jar或者war格式,同时还需要使用Java命令,本文主要介绍了maven插件maven-assembly-plugin打包归纳文件zip/tar使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • Java 设计模式以虹猫蓝兔的故事讲解建造者模式

    Java 设计模式以虹猫蓝兔的故事讲解建造者模式

    建造者模式,是一种对象构建模式 它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不同实现方法可以构造出不同表现的对象。本文将通过示例讲解建造者模式,需要的可以参考一下
    2022-04-04
  • SpringCloud协同开发实现方法浅析

    SpringCloud协同开发实现方法浅析

    好几个人同时开发同一个服务上的不同模块,导致你需要调试的接口总是被路由到别人的服务上,非常影响调试的效率,而且人越多越难受,总是请求不到自己的服务,这篇文章主要介绍了SpringCloud协同开发实现方法
    2022-12-12
  • Java Spring的核心与设计思想你知道吗

    Java Spring的核心与设计思想你知道吗

    这篇文章主要为大家详细介绍了Java Spring的核心与设计思想,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • Java11中基于嵌套关系的访问控制优化详解

    Java11中基于嵌套关系的访问控制优化详解

    Java(和其他语言)通过内部类支持嵌套类,要使其正常工作,需要编译器执行一些技巧,下面这篇文章主要给大家介绍了关于Java11中基于嵌套关系的访问控制优化的相关资料,需要的朋友可以参考下
    2022-01-01
  • JAVA调用JavaScript方法代码示例

    JAVA调用JavaScript方法代码示例

    之前在一次机缘巧合的情况下,需要时用JAVA执行js方法,查阅了一些文档,找到了相关解决方法,这里和大家分享一下,这篇文章主要给大家介绍了关于JAVA调用JavaScript方法的相关资料,需要的朋友可以参考下
    2023-09-09
  • java开发中防止重复提交的几种解决方案

    java开发中防止重复提交的几种解决方案

    我们日常开发中有很多的应用场景都会遇到重复提交问题,下面这篇文章主要给大家介绍了关于java开发中防止重复提交的几种解决方案,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • Java Volatile关键字你真的了解吗

    Java Volatile关键字你真的了解吗

    这篇文章主要为大家介绍了Java Volatile关键字,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2021-12-12
  • Spring Boot优雅使用RocketMQ的方法实例

    Spring Boot优雅使用RocketMQ的方法实例

    这篇文章主要给大家介绍了关于Spring Boot优雅使用RocketMQ的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12

最新评论