zoukankan      html  css  js  c++  java
  • 关于多线程工作内存何时会刷新的问题探讨

    JMM 用来定义程序中变量的访问规则,定义者,想要屏蔽掉不同的硬件和系统造成的内存访问差异。

    之前了解的JMM空也曾提到工作内存的概念,每个线程都有自己的工作内存,所有的变量多存在主内存,工作内存存储的是各个线程用到的变量 主内存的副本拷贝,工作内存之间不能直接操作对方工作内存的变量,要通过主内存作为中间介,各个线程只能操作各自的工作线程变量,无法直接操作主内存变量。

    然后就是就是定义了8中原子操作,用来控制变量,分别是 lock、unlock,read、load、use、assign、store、write。

    定义了8个规则

    1一个变量只能被一个线程lock,能被同一个线程多次lock,相应的要多次unlock,后面说的就是可重入。

    2lock一个变量后,清除自己的工作内存先,再要使用时,重新从主内存加载;unlock后,要同步到主内存。

    3变量只能定义在主内存,在使用user或者store前要load  或者assign

    4工作内存的变量没变化,不能平白无故同步主内存,一旦改变一定要同步主内存。

    以上是基础知识。摘自《深入了解java虚拟机》

    再遇到两个线程同时操作一个对象的字段时,遇到了一些问题,

    先贴代码

    public class MyObject {
    private String name="1";
    private String pass="11";

    public void print() {
    System.out.println(name+" "+pass);
    }

    public void setvalue(String u,String p){
    this.name=u;
    if(Thread.currentThread().getName().equals("a")){
    System.out.println("a停止 ");
    Thread.currentThread().suspend();
    }
    this.pass=p;
    }
    }
    public class Test {
    public static void main(String[] args) throws Exception{
    final MyObject object = new MyObject();
    Thread thread2 = new Thread(){
    @Override
    public void run() {
    while (true){
    object.print();
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    };
    thread2.start();

    Thread thread1 = new Thread(){
    @Override
    public void run() {
    object.setvalue("a","aa");
    }
    };

    thread1.setName("a");
    thread1.start();
    Thread.sleep(500);

    //thread2.start();

    }

    描述:thread2和Thread1 会同时去操作一个object对象,
    thread2运行后,输出的 是1和11,在Thread1启动后,会改变object的字段值,这时候thread2循环输出的也变了,变成了a和11.

    思考:
    1每个线程都有自己的工作内存,会把object对象(字段为1,11)拷贝一份到thread2和Thread1的各自工作内存,第一次 thread2输出字段为(1,11)可以理解。
    2但是当Thread1  启动后改变了期工作内存的object字段变成(a,11),
    3接下来
    thread2输出字段为也变成了 (a,11)
    于是接在思考不是有各自的工作内存吗,线程thread1也没有停止啊,为什么线程thread2的工作内存变量也会变掉。

    以下是自己的看法
    线程thread1的suspend()方法会同步到主内存,还有sleep()也是如此。
    然后接下来就是怎么 主内存同步到 线程thread2的工作内存中

    这是别人见解
    为了提升性能,线程里面有工作内存,这样访问数据不用去主存读取,可以快一些。共享变量被线程修改后,该线程的工作内存中的值就会和其他线程不一致,也和主存的值不一致,所以需要将工作内存的值刷入主存,但是这个刷入可能其他线程并没有看到。
    使用 volatile 后可以通过 cpu 指令屏障强制要求读操作发生在写操作之后,并且其他线程在读取该共享变量时,需要先清理自己的工作内存的该值,转而重新从主存读取,volatile 保证一定会刷新,但是不写也不一定其他线程看不见。

    就是不一定,有随机性,不加voliatile其他线程 也不一定看不见。加了一定看的见。
    这就是目前我的理解。



  • 相关阅读:
    ViewModel和LiveData问题思考与解答
    vps_centos_7_系统环境常规配置备忘
    JVM内存管理&GC
    sping注解
    ibatis order by 防止sql注入
    好用的绿色工具(mss2sql,jd-gui)
    mysql优化
    Spring事务
    好文分享_java堆栈的区别
    Linux usual cmd
  • 原文地址:https://www.cnblogs.com/xlblog/p/11520793.html
Copyright © 2011-2022 走看看