根据提供的文件信息,我们可以归纳出以下关键知识点: ### 1. volatile 的用途 #### 1.1 线程可见性 在Java中,`volatile`关键字被用来确保线程间变量修改的可见性。当一个线程修改了一个声明为`volatile`的变量时,其他线程能够立即看到这一变化。这主要通过禁止编译器和处理器进行某些类型的优化来实现,这些优化可能会导致线程看不到最新的变量值。 #### 示例代码分析 下面的示例展示了如何使用`volatile`来确保线程间的可见性。 ```java package com.mashibing.testvolatile; public class T01_ThreadVisibility { private static volatile boolean flag = true; public static void main(String[] args) throws InterruptedException { new Thread(() -> { while (flag) { // do something } System.out.println("end"); }, "server").start(); Thread.sleep(1000); flag = false; } } ``` 在这个例子中,`flag`被声明为`volatile`,因此当主线程改变它的值时,新值将立刻对其他线程可见。这样,`server`线程就会检测到`flag`的变化,并退出循环。 ### 2. 防止指令重排序 #### 2.1 DCL 单例是否需要加 volatile? **双重检查锁定(Double-Checked Locking, DCL)**是一种用于创建线程安全的单例模式的方法。然而,在Java中如果没有正确使用`volatile`,则可能导致DCL单例出现异常。这是因为对象的构造过程可能被编译器或者处理器重排序。 #### 2.2 CPU 缓存基础知识 - **缓存行对齐**:缓存行通常包含64个字节的数据,这是CPU读取或写入数据的基本单位。如果多个线程访问同一个缓存行的不同位置,可能会因为缓存一致性问题而降低性能,这种现象称为“伪共享”。 - **MESI 协议**:MESI(Modified Exclusive Shared Invalid)是一种常用的缓存一致性协议,它通过跟踪缓存行的状态来保持多处理器系统中的缓存一致性。 #### 2.3 示例代码分析 ```java package com.mashibing.juc.c_028_FalseSharing; public class T02_CacheLinePadding { private static class Padding { public volatile long p1, p2, p3, p4, p5, p6, p7; } private static class Textends Padding { public volatile long x = 0L; } public static T[] arr = new T[2]; static { arr[0] = new T(); arr[1] = new T(); } public static void main(String[] args) throws Exception { Thread t1 = new Thread(() -> { for (long i = 0; i < 1000_0000L; i++) { arr[0].x = i; } }); Thread t2 = new Thread(() -> { for (long i = 0; i < 1000_0000L; i++) { arr[1].x = i; } }); final long start = System.nanoTime(); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println((System.nanoTime() - start) / 100_0000); } } ``` 在这个示例中,我们使用了缓存行填充技术(Cache Line Padding),即在类`T`中添加了7个`volatile long`字段来避免伪共享。通过这种方式,每个线程都在自己的缓存行上操作,从而提高了并发性能。 ### 3. 合并写(Write Combining) #### 3.1 合并写的概念 合并写是现代CPU提供的一种机制,用于减少内存访问次数。当CPU检测到多次连续写入同一地址时,它会把这些写操作合并起来执行一次,从而提高性能。 #### 3.2 示例代码分析 ```java package com.mashibing.juc.c_029_WriteCombining; public final class WriteCombining { private static final int ITERATIONS = Integer.MAX_VALUE; private static final int ITEMS = 1 << 24; private static final int MASK = ITEMS - 1; private static final byte[] arrayA = new byte[ITEMS]; private static final byte[] arrayB = new byte[ITEMS]; private static final byte[] arrayC = new byte[ITEMS]; private static final byte[] arrayD = new byte[ITEMS]; private static final byte[] arrayE = new byte[ITEMS]; private static final byte[] arrayF = new byte[ITEMS]; public static void main(final String[] args) { for (int i = 1; i <= 3; i++) { System.out.println(i + " Single Loop duration(ns)=" + runCaseOne()); System.out.println(i + " Split Loop duration(ns)=" + runCaseTwo()); } } public static long runCaseOne() { long start = System.nanoTime(); int i = ITERATIONS; while (--i != 0) { int slot = i & MASK; byte b = (byte) i; arrayA[slot] = b; arrayB[slot] = b; arrayC[slot] = b; arrayD[slot] = b; arrayE[slot] = b; arrayF[slot] = b; } return System.nanoTime() - start; } public static long runCaseTwo() { // ... 示例中未完全给出runCaseTwo方法的实现 } } ``` 在这个示例中,通过比较单循环和分段循环的执行时间来展示合并写的效果。在`runCaseOne`方法中,所有的数组更新操作都放在一个循环里,这可能会触发合并写机制,从而减少实际的内存访问次数,提高程序运行速度。 总结以上内容,我们可以了解到`volatile`关键字在Java多线程中的重要作用以及相关的CPU缓存管理和优化技术。这些知识点对于理解并发编程中的内存模型和性能调优至关重要。













- 粉丝: 1
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- 详解如何进行毕业论文答辩.docx
- 最新经济学理论论文答辩.docx
- 自考法律本科论文答辩推荐.docx
- 人工智能与机器学习相关课程组成的课程群
- 《机器学习实战:基于 Python 3 版本的实践指南》
- 学堂在线张敏老师主讲的《机器学习》实验课
- One Night In Shanghai (cover, 胡彦斌)-兰音Reine.mp3
- 学习笔记-机器学习与经济学
- 热门实用的机器学习与深度学习 Python 库及工具合集
- a collection of awesome machine learning and deep learning Python libraries&tools. 热门实用机器学习和深入学习Pyth
- 机器学习算法的代码实现方法与示例
- 基于GD32的多目标实时识别系统
- 基于GD32的单目标实时跟踪系统
- ggdq10.81.0.1.apk
- 吴恩达机器学习算法的 Python 实现及详细代码注释
- 基于机器学习的恶意 URL 检测优化方案


