• 92428

    文章

  • 775

    评论

  • 17

    友链

  • 最近新加了换肤功能,大家多来逛逛吧~~~~
  • 喜欢这个网站的朋友可以加一下QQ群,我们一起交流技术。

Java 内存模型

撸了今年阿里、腾讯和美团的面试,我有一个重要发现.......>>

物理机并发处理方案

        绝大多数计算任务,并不是单纯依赖 cpu 的计算完成,不可避免需要与内存交互,获取数据。内存要拿到数据,需要和硬盘发生 I/O 操作。计算机存储设备与 cpu 之间的处理速度有几个数量级的差距。现代计算机为了减少这种差距,在 cpu 与内存之间加了一层高速缓存(cache)。这样就可以减少缓慢的内存读写。但这样做,在多处理器环境下共享一块主内存,就会产生缓存一致性问题。这时进行运算时就需要遵守很多协议,比如 MSI、MESI、MOSI等。

         为了使得处理器内部的运算单元能够得到充分利用,除了增加高速缓存外,处理器会对输入的代码进行乱序执行,保证执行结果与顺序执行一致。与处理器的乱序执行类似,Java 语言即时编译器也有类似的指令重排序优化;

Java 内存模型

        Java 内存模型规定,所有的变量都存储在主内存。每个线程有自己的工作内存。工作内存使用的变量来自于主内存中变量的拷贝。线程对变量的操作必须在各自的工作内存值进行,不能直接读写主内存中的变量。不同线程也无法访问对方的工作内存中的变量。线程之间变量的传递均需要经过主内存。

    工作内存与主内存之间定义了很多交互协议,以保证主内存变量的一致性,这也可以类比物理机的类似协议。Java 内存模型定义了 8 种 操作,JVM 会保证这每一种操作都是原子的。8 种操作有: 

  •  lock(锁定): 作用于主内存变量,把变量标记为一条线程独有的;

  • unlock(解锁): 作用于主内存变量,把变量从锁定状态解锁,其他线程才可以使用;

  • read(读取):  作用于主内存变量,把一个变量的值从主内存传递到其他内存,以便 load 动作使用;

  • load(载入): 作用于工作内存变量,把read 值放入工作内存副本;

  • use(使用):  作用于工作内存变量,把工作内存的值传给执行引擎;

  • assign(赋值): 作用于工作内存变量,把执行引擎接受到的值给工作内存的变量;

  • store(存储):  作用于工作内存变量,把工作内存变量传给主内存,以便 write 操作使用;

  • write(写入):  作用于主内存变量,把 store 操作拿到的变量写入主内存变量;

Java 内存模型的建立是围绕并发情况下,如何处理原子性、有序性和可见性建立的:

  1. 原子性:由Java 内存模型保证的原子性操作有 read, load, assign, use, store, 和 write.如果需要在更大的一个范围内保证操作的原子性,可以使用字节码指令 monitorenter 和 monitorexit。也就是synchronized 关键字;
  2. 可见性:一个线程修改了共享变量的值后,对其他所有线程立即可见,可以使用 volatile 关键字来实现,它可以保证一个线程修改了工作线程的值之后,可以立即同步到主内存。也可以使用synchronized 因为对一个变量执行 unlock 操作之前,必须把此变量修改后的值同步回主内存;final 修饰的变量在构造器中一旦初始化完成,没有发生 this引用逃逸,其他线程就能看到该字段的值。
  3. 有序性: volatile(禁止指令重排序) 和 synchronized (一次只允许一个线程执行 lock 操作)可以保证线程之间操作的有序性;Java 语言有一个先行发生的原则,也可以保证有序性;

参考 : 深入理解 Java 虚拟机


695856371Web网页设计师②群 | 喜欢本站的朋友可以收藏本站,或者加入我们大家一起来交流技术!

欢迎来到梁钟霖个人博客网站。本个人博客网站提供最新的站长新闻,各种互联网资讯。 还提供个人博客模板,最新最全的java教程,java面试题。在此我将尽我最大所能将此个人博客网站做的最好! 谢谢大家,愿大家一起进步!

转载原创文章请注明出处,转载至: 梁钟霖个人博客www.liangzl.com

0条评论

Loading...


发表评论

电子邮件地址不会被公开。 必填项已用*标注

自定义皮肤
注册梁钟霖个人博客