`
catalin
  • 浏览: 16201 次
  • 来自: ...
社区版块
存档分类
最新评论

Java多线程初学者指南(9):为什么要进行数据同步-2

阅读更多

也许有人会问,如果只有n++,会产生“脏数据”吗?答案是肯定的。那么n++只是一条语句,又如何在执行过程中将CPU交给其他的线程呢?其实这只是表面现象,n++在被Java编译器编译成中间语言(也叫做字节码)后,并不是一条语言。让我们看看下面的Java代码将会被编译成什么样的Java中间语言。

Java源代码

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->public void run()
{
    n
++;
}

被编译后的中间语言代码

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->  001  public void run()
  
002  {
  
003      aload_0         
  
004      dup             
  
005      getfield
  
006      iconst_1        
  
007      iadd            
  
008      putfield       
  
009      return          
  
010  }

 

大家可以看到在run方法中只有n++一条语句,而在编译后,却有7条中间语言语句。我们并不需要知道这些语句的功能是什么,只看一下第005007008行语句。在005行是getfield,根据它的英文含义可知是要得到某个值,因为这里只有一个n,所以毫无疑问,是要得到n的值。而在007行的iadd也不难猜测是将这个得到的n值加1。在008行的putfield的含义我想大家可能已经猜出来了,它负责将这个加1后的n再更新回类变量n。说到这,可能大家还有一个疑惑,执行n++时直接将n1不就行了,为什么要如此费周折。其实这里涉及到一个Java内存模型的问题。

Java的内存模型分为主存储区和工作存储区。主存储区保存了Java中所有的实例。也就是说,在我们使用new来建立一个对象后,这个对象及它内部的方法、变量等都保存在这一区域,在MyThread类中n就保存在这个区域。主存储区可以被所有线程共享。而工作存储区就是我们前面所讲的线程栈,在这个区域里保存了在run方法以及run方法所调用的方法中定义的变量,也就是方法变量。在线程要修改主存储区中的变量时,并不是直接修改这些变量,而是将它们先复制到当前线程的工作存储区,在修改完后,再将这个变量值覆盖主存储区的相应的变量值。

在了解了

Java

的内存模型后,就不难理解为什么

n++

也不是原子操作了。它必须经过一个拷贝、加

1

和覆盖的过程。这个过程和在MyThread类中模拟的过程类似。大家可以想象,如果在执行到

getfield

时,

thread1

由于某种原因被中断,那么就会发生和MyThread类的执行结果类似的情况。要想彻底解决这个问题,就必须使用某种方法对n进行同步,也就是在同一时间只能有一个线程操作n,这也称为对n的原子操作。

分享到:
评论

相关推荐

    Java多线程初学者指南

    Java多线程初学者指南,共12篇文档,由浅入深,举例说明,包括一些疑点都解释得很清楚,类,方法,属性同步的区别等细节也都介绍得很全面,是个很好的学习资料。

    【并发编程】CAS到底是什么.pdf

    中级开发者:已经具备一定的编程经验,希望提高程序性能或学习多线程开发的人员。 高级开发者:需要深入理解并发编程原理,解决复杂并发问题的资深开发者。 计算机科学学生:正在学习计算机科学,对并发和分布式系统...

    【并发编程】volatile的原理我好像又懂了.pdf

    中级开发者:已经具备一定的编程经验,希望提高程序性能或学习多线程开发的人员。 高级开发者:需要深入理解并发编程原理,解决复杂并发问题的资深开发者。 计算机科学学生:正在学习计算机科学,对并发和分布式系统...

    【并发编程】自定义简单线程池.pdf

    中级开发者:已经具备一定的编程经验,希望提高程序性能或学习多线程开发的人员。 高级开发者:需要深入理解并发编程原理,解决复杂并发问题的资深开发者。 计算机科学学生:正在学习计算机科学,对并发和分布式系统...

    【并发编程】简单化理解AQS和ReentrantLock.pdf

    中级开发者:已经具备一定的编程经验,希望提高程序性能或学习多线程开发的人员。 高级开发者:需要深入理解并发编程原理,解决复杂并发问题的资深开发者。 计算机科学学生:正在学习计算机科学,对并发和分布式系统...

    【并发编程】如何优雅使用线程池.pdf

    中级开发者:已经具备一定的编程经验,希望提高程序性能或学习多线程开发的人员。 高级开发者:需要深入理解并发编程原理,解决复杂并发问题的资深开发者。 计算机科学学生:正在学习计算机科学,对并发和分布式系统...

    【并发编程】深入理解JMM.pdf

    中级开发者:已经具备一定的编程经验,希望提高程序性能或学习多线程开发的人员。 高级开发者:需要深入理解并发编程原理,解决复杂并发问题的资深开发者。 计算机科学学生:正在学习计算机科学,对并发和分布式系统...

    Eclipse权威开发指南2.pdf

    5.3 为初学者准备的CVS概述...... 133 5.3.1 CVS的一些重要设计原则..... 133 5.3.2 修订版:任何东西都不会被丢失..... 134 5.3.3 更新:跟上小组的进度..... 134 5.3.4 提交:共享您的资源..... 134 5.3.5 版本...

    Eclipse权威开发指南3.pdf

    5.3 为初学者准备的CVS概述...... 133 5.3.1 CVS的一些重要设计原则..... 133 5.3.2 修订版:任何东西都不会被丢失..... 134 5.3.3 更新:跟上小组的进度..... 134 5.3.4 提交:共享您的资源..... 134 ...

    asp.net知识库

    ADO.NET 2.0 大批量数据操作和多个动态的结果集 ADO.NET 2.0 异步处理 在ASP.NET中使用WINDOWS验证方式连接SQL SERVER数据库 改进ADO.Net数据库访问方式 ASP.NET 2.0 绑定高级技巧 简单实用的DataSet更新数据库的类+...

    Eclipse权威开发指南1.pdf

    5.3 为初学者准备的CVS概述...... 133 5.3.1 CVS的一些重要设计原则..... 133 5.3.2 修订版:任何东西都不会被丢失..... 134 5.3.3 更新:跟上小组的进度..... 134 5.3.4 提交:共享您的资源..... 134 ...

Global site tag (gtag.js) - Google Analytics