您的位置:网站首页 > Java工具 > 正文

Java内存模型小析

类别:Java工具 日期:2018-1-28 21:19:26 人气: 来源:

  一个操作或一系列是不可中断的。即使是在多个线程一起执行的时候,这些操作一旦开始,就不会被其他线程干扰

  JMM中不:在32位的处理器上对64位的long型和double型变量的写操作具有原子性。(当JVM在这种处理器上运行时,可能会把一个64位long/double型变量的写操作拆分为两个32位的写操作来执行)。

  我们说过i++的复合操作不具有原子性。那么i++操作为什么不具有原子性呢?因为i++这个操作至少可以分为下面这三个步骤:先读i的i值,对i的值进行加1的操作,然后将修改过i的值写入到内存中。即读--改--写操作。这样在并发编程中就会出现问题了,如下所示:

  CPU1和CPU2同时从各自的缓存中读取变量i,分别进行加1的操作,然后分别写入系统内存中。我们之前可能的期望可能是:CPU1+1,CPU2+1结果应该是+2,但是可能的结果确实+1。但是处理器可以通过总线锁定和缓存锁定来解决这个问题。简单说就是:CPU1在读改写共享变量的时候,CPU2不能操作缓存了该共享变量内存地址的缓存。

  所谓总线锁定就是使用处理器提供的一个LOCK#信号,当一个处理器在总线上输出此信号时,其他处理器的请求将被阻塞住,那么该处理器可以独占共享内存。但是总线锁定会有性能问题,因为在同一时刻,我们只需对某个内存地址的操作是原子性即可,但是总线锁定把CPU和内存之间的通信锁住了,这使得锁定期间,其他处理器不能操作其他内存地址的数据。这个性能上的损耗常大的。

  在多处理器下,为了各个处理器的缓存是一致的,就会实现缓存一致性协议,每个处理器通过嗅探在总线上的数据来检查自己缓存的值是不是过期了,当处理器

  发现自己缓存行对应的内存地址被修改,就会将当前处理器得到缓存行设置成无效状态,当处理器对这个数据进行修改操作的时候,会重新从系统内存中把数据读到

  频繁使用的内存会缓存在处理器的L1、L2和L3高速缓存里,那么如果我们要操作的数据在同一个缓存行里,那么我们就可以直接对这个缓存行进行锁定就行了。所以缓存锁定是值内存区域如果被缓存在处理器的和缓存行中,并且在LOCK操作期间被锁定,那么当它执行锁操作回写到内存时,处理器不在总线上声言LOCK#信号,而是修改缓存行的内存地址,并允许它的缓存一致性机制来操作的原子性。因为缓存一致性机制会同时修改由两个以上处理器缓存行的内存区域数据,当其他处理器回写已被锁定的缓存行的数据时,会使和缓存行无效。

  但是每一次,只能有一个线程使用它,一旦临界区资源被占用,其他线程要想使用这个资源,就必须等待

  java中的并发采用的是共享内存模型的方式。共享内存是什么呢?我们知道JVM中堆内存和方法区(这里区分开来了)是在线程之间共享的。那么这部分内存都包含什么东西呢?包含实例域、静态域、数组元素等。它们又可以称为

  。 java并发线程之间的通信是由java内存模型(JMM)控制的,JMM决定了一个线程对共享变量的写入何时对另一个线程可见(

  !)。JMM可以做这样的一个抽象:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存(或者成为工作内存),本地内存中存储了该线程读-写共享变量的副本。本地内存是JMM的一个抽象概念,它涵盖了缓存、写缓冲区、寄存器以及其他的硬件和编译器优化。如下图所示:

  知道这个修改。我们在并发编程遇到了一个大的问题是可见性问题,即一个线程对一个共享变量修改的值,另外一个线程读不到这个修改后的值。引起可见性问题的原因有很多,像编译器优化,处理器优化等等。

  现代处理器使用写缓冲区临时保存向内存写入的数据,写缓冲区可以指令流水线持续运行,它可以避免由于处理器停顿下来等待向内存写入数据而产生的延迟。同时,通过以批处理的方式刷新写缓冲区,以及合并写缓冲区对同一内存地址的多次写,减少对内存总线的占用。每个处理器上的写缓冲区,仅仅对它所在的处理器可见(会引起可见性问题)。这个特性会导致处理器对内存的读/写操作的执行顺序不一定与内存实际发生的读/写操作顺序一致。

  

关键词:java清理缓存
0
0
0
0
0
0
0
0
下一篇:没有资料

网友评论 ()条 查看

姓名: 验证码: 看不清楚,换一个

推荐文章更多

热门图文更多

最新文章更多

关于联系我们 - 广告服务 - 友情链接 - 网站地图 - 版权声明 - 人才招聘 - 帮助

郑重声明:本站资源来源网络 如果侵犯了你的利益请联系站长删除

CopyRight 2010-2012 技术支持 FXT All Rights Reserved