关于多线程工作内存何时会刷新的问题探讨

Posted xlblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于多线程工作内存何时会刷新的问题探讨相关的知识,希望对你有一定的参考价值。

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其他线程 也不一定看不见。加了一定看的见。
这就是目前我的理解。



以上是关于关于多线程工作内存何时会刷新的问题探讨的主要内容,如果未能解决你的问题,请参考以下文章

java多线程并发去调用一个类的静态方法安全性探讨

线程池参数设置问题探讨

[转]java多线程并发去调用一个类的静态方法安全性探讨

多线程中的两个问题探讨

关于JVM内存溢出的原因分析及解决方案探讨

NSThead的进阶使用和简单探讨