探索并发编程(三)------Java存储模型和共享对象

发表于:2011-9-22 09:51

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:cutesource    来源:51Testing软件测试网采编

  很多程序员对一个共享变量初始化要注意可见性和安全发布(安全地构建一个对象,并其他线程能正确访问)等问题不是很理解,认为Java是一个屏蔽内存细节的平台,连对象回收都不需要关心,因此谈到可见性和安全发布大多不知所云。其实关键在于对Java存储模型,可见性和安全发布的问题是起源于Java的存储结构。

  Java存储模型原理

  有很多书和文章都讲解过Java存储模型,其中一个图很清晰地说明了其存储结构:

  由上图可知, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。 每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。

  这个存储模型很像我们常用的缓存与数据库的关系,因此由此可以推断JVM如此设计应该是为了提升性能,提高多线程的并发能力,并减少线程之间的影响。

  Java存储模型潜在的问题

  一谈到缓存, 我们立马想到会有缓存不一致性问题,就是说当有缓存与数据库不一致的时候,就需要有相应的机制去同步数据。同理,Java存储模型也有这个问题,当一个线程在自己工作内存里初始化一个变量,当还没来得及同步到主存里时,如果有其他线程来访问它,就会出现不可预知的问题。另外,JVM在底层设计上,对与那些没有同步到主存里的变量,可能会以不一样的操作顺序来执行指令,举个实际的例子:

  • public class PossibleReordering {  
  •     static int x = 0, y = 0;  
  •     static int a = 0, b = 0;  
  •     public static void main(String[] args)  
  •             throws InterruptedException {  
  •         Thread one = new Thread(new Runnable() {  
  •             public void run() {  
  •                 a = 1;  
  •                 x = b;  
  •             }  
  •         });  
  •         Thread other = new Thread(new Runnable() {  
  •             public void run() {  
  •                 b = 1;  
  •                 y = a;  
  •             }  
  •         });  
  •         one.start(); other.start();  
  •         one.join();   other.join();  
  •         System.out.println("( "+ x + "," + y + ")");  
  •     }  
  • }
  •   由于,变量x,y,a,b没有安全发布,导致会不以规定的操作顺序来执行这次四次赋值操作,有可能出现以下顺序:

      出现这个问题也可以理解,因为既然这些对象不可见,也就是说本应该隔离在各个线程的工作区内,那么对于有些无关顺序的指令,打乱顺序执行在JVM看来也是可行的。

      因此,总结起来,会有以下两种潜在问题:

      ● 缓存不一致性

      ● 重排序执行

    31/3123>
    《2023软件测试行业现状调查报告》独家发布~

    关注51Testing

    联系我们

    快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

    法律顾问:上海兰迪律师事务所 项棋律师
    版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
    投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

    沪ICP备05003035号

    沪公网安备 31010102002173号