From 9c246fafb4215118189929174f82dd46496eb3df Mon Sep 17 00:00:00 2001 From: zhangshiyu <1946955309@qq.com> Date: Tue, 25 Oct 2022 21:39:36 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E5=AE=8C=E5=96=84"=E5=A6=82=E4=BD=95?= =?UTF-8?q?=E4=BF=9D=E8=AF=81=E5=8F=98=E9=87=8F=E7=9A=84=E5=8F=AF=E8=A7=81?= =?UTF-8?q?=E6=80=A7"=E9=97=AE=E9=A2=98=E7=AD=94=E6=A1=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/java/concurrent/java-concurrent-questions-02.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/java/concurrent/java-concurrent-questions-02.md b/docs/java/concurrent/java-concurrent-questions-02.md index 2db9e978c5c..91a0bda1e26 100644 --- a/docs/java/concurrent/java-concurrent-questions-02.md +++ b/docs/java/concurrent/java-concurrent-questions-02.md @@ -20,7 +20,7 @@ JMM(Java 内存模型)相关的问题比较多,也比较重要,于是我 ### 如何保证变量的可见性? -在 Java 中,`volatile` 关键字可以保证变量的可见性,如果我们将变量声明为 **`volatile`** ,这就指示 JVM,这个变量是共享且不稳定的,每次使用它都到主存中进行读取。 +在 Java 中,`volatile` 关键字底层是基于总线嗅探机制和MESI缓存一致性协议保证变量的可见性,如果我们将变量声明为 **volatile** ,这就指示CPU,这个变量是共享且不稳定的,每次使用它时,处理器都会判断这个变量在缓存行中的状态是否因为其他处理器的修改变成无效(Invalid),若无效则重新从系统内存中把数据读取到处理器缓存。 ![](https://guide-blog-images.oss-cn-shenzhen.aliyuncs.com/github/javaguide/java/concurrent/jmm.png) From 6ecfecc8514201eb95c27b067c28499352c1e6ea Mon Sep 17 00:00:00 2001 From: zhangshiyu <1946955309@qq.com> Date: Tue, 1 Nov 2022 20:55:30 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20"3.3.7=20Eden=E5=B9=B4?= =?UTF-8?q?=E8=BD=BB=E4=BB=A3=E7=9A=84=E4=BB=8B=E7=BB=8D"=20=E8=AF=AD?= =?UTF-8?q?=E5=8F=A5=E4=B8=8D=E9=A1=BA=E7=9A=84=E5=8F=A5=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/java/jvm/jvm-intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/java/jvm/jvm-intro.md b/docs/java/jvm/jvm-intro.md index 5f7f0ea1d4a..482acde9e8f 100644 --- a/docs/java/jvm/jvm-intro.md +++ b/docs/java/jvm/jvm-intro.md @@ -207,7 +207,7 @@ JVM内存会划分为堆内存和非堆内存,堆内存中也会划分为**年 #### 3.3.7 Eden年轻代的介绍 -当我们new一个对象后,会先放到Eden划分出来的一块作为存储空间的内存,但是我们知道对堆内存是线程共享的,所以有可能会出现两个对象共用一个内存的情况。这里JVM的处理是每个线程都会预先申请好一块连续的内存空间并规定了对象存放的位置,而如果空间不足会再申请多块内存空间。这个操作我们会称作TLAB,有兴趣可以了解一下。 +当我们new一个对象后,会先放到Eden划分出来的一块作为存储空间的内存,但是我们知道对堆内存是线程共享的,所以有可能会出现两个对象共用一个内存的情况。这里JVM的处理是为每个线程都预先申请好一块连续的内存空间并规定了对象存放的位置,而如果空间不足会再申请多块内存空间。这个操作我们会称作TLAB,有兴趣可以了解一下。 当Eden空间满了之后,会触发一个叫做Minor GC(就是一个发生在年轻代的GC)的操作,存活下来的对象移动到Survivor0区。Survivor0区满后触发 Minor GC,就会将存活对象移动到Survivor1区,此时还会把from和to两个指针交换,这样保证了一段时间内总有一个survivor区为空且to所指向的survivor区为空。经过多次的 Minor GC后仍然存活的对象(**这里的存活判断是15次,对应到虚拟机参数为 -XX:MaxTenuringThreshold 。为什么是15,因为HotSpot会在对象投中的标记字段里记录年龄,分配到的空间仅有4位,所以最多只能记录到15**)会移动到老年代。老年代是存储长期存活的对象的,占满时就会触发我们最常听说的Full GC,期间会停止所有线程等待GC的完成。所以对于响应要求高的应用应该尽量去减少发生Full GC从而避免响应超时的问题。