Java并发-1(一)内存可见性
来源:互联网 发布:mac ds store 文件 编辑:程序博客网 时间:2024/06/14 14:58
线程学习之后,大概了解了线程的功能和原理,这里不再赘述。
什么是内存可见性呢?
当若干个线程共享同一个资源的时候,这个资源就处于临界状态,如果处理不当很容易发生一些不愿意看到的错误。
举个栗子:
- 创建一个ThreadDemo类实现Runnable接口
- 有一个boolean的变量flg默认值是false
- 在run()方法中改变flg的值为true
- 然后在main方法中创建一个线程执行start方法
- 在线程中判断flg的值是否是true,并打印语句
class ThreadDemo implements Runnable{ private boolean flg = false; @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } this.flg = true; System.out.println("ThreadDemo.run()->flg:"+this.flg); } public boolean isFlg() { return flg; } public void setFlg(boolean flg) { this.flg = flg; }}
TestVolatile类和main方法
public class TestVotile { public static void main(String[] args) { ThreadDemo td = new ThreadDemo(); new Thread(td).start(); while(true){ if(td.isFlg()){ System.out.println("CurrentThread->"); break; } } }}
执行main方法之后观察测试结果:
结果令人感到意外?而且发现eclipse上的红色按钮表示程序并没有结束而是一直再循环。
原因分析
在多线程中JVM虚拟机为了优化和提高效率,为每一个线程都提供了一个单独的缓存空间。这样在这个例子中共享变量flg就产生了三个空间,一个是主存,在堆中,另外两个一个在线程td的缓存中,另外一个在main线程的缓存中。
如图所示:
在td线程拿到flg之后放在自己的缓存中,并且修改flg为true然后把修改后的值刷新到主内存中,但是由于main线程的while循环效率非常高,在主内存的值被刷新之前就获得到了flg的值,为false,所以不会执行打印语句,即便是主存中的flg值已经被刷新了,但是由于while的影响,没机会在主内存中多的最新的值,导致flg在main的while中一直是false,一直处于循环状态什么都不做。而且主线程也不会结束。
volatile关键字
对于上属于的问题就是内存可见性的问题,在TreadDemo类想flg变量之前加上volatile修饰符,使得双方的操作的共享资源可以及时的得到更新,甚至可以看成双方对共享资源的操作就是指主存中进行的,而且共享资源的的改变可以被任何一个线程得到,这样就保证了内存的可见性。
class ThreadDemo implements Runnable{ private volatile boolean flg = false; @Override public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } this.flg = true; System.out.println("ThreadDemo.run()->flg:"+this.flg); } public boolean isFlg() { return flg; } public void setFlg(boolean flg) { this.flg = flg; }}
再次测试输出结果为
此时线程结束,主线程也打印了语句。
1 0
- Java并发-1(一)内存可见性
- 【Java并发】内存可见性
- Java并发:volatile内存可见性和指令重排
- Java并发:volatile内存可见性和指令重排
- Java并发:volatile内存可见性和指令重排
- Java并发2——内存可见性
- Java并发:volatile内存可见性和指令重排
- Java并发:volatile内存可见性和指令重排
- Java并发:volatile内存可见性和指令重排
- Java并发:volatile内存可见性和指令重排
- Java并发:volatile内存可见性和指令重排
- java并发编程(八)--synchronized的另个一重要作用:内存可见性
- Java并发编程(14):图文讲述同步的另一个重要功能—内存可见性
- java并发之原子性与可见性(一)
- java并发之原子性与可见性(一)
- java并发之原子性与可见性(一)
- java内存可见性
- java内存可见性
- oracle 10g 导入到11g
- CentOS升级Python2.6到Python2.7并安装pip
- LintCode 61 搜索区间
- web.鼠标.跟着鼠标走的事件
- selector标签 与 Drawable State详解
- Java并发-1(一)内存可见性
- 【Splay练习】
- hdu 1004 Let the Balloon Rise
- Java IO流之缓冲流
- 对ACProtect1.32壳的分析以及对抽取代码的修补
- Struts2的优势及其工作原理
- Javascript引用类型之Array类型(一)
- Mastering Opencv ch4:SFM详解(二)
- 绪论