博客
关于我
Java volatile使用详细说明-可见性的详细讲解
阅读量:696 次
发布时间:2019-03-17

本文共 1849 字,大约阅读时间需要 6 分钟。

Java多线程之同步与易失性

在学习多线程编程时,同步和易失性是两个关键概念。前篇已经探讨了同步的骚操作,本篇将深入分析同步状语从句,了解其与易失性之间的区别,易失性的使用条件,以及虚拟机层面的一些实现细节。


本文要点

  • 同步与易失性特性差异
  • 使用易失性需要满足的条件
  • 易失性特性在虚拟机层面的实现
  • 易失性示例代码

  • 1. 同步与易失性特性差异

    1.1 可见性和原子性

    • synchronized保证了可见性和原子性。
    • volatile仅保证可见性,不具备原子性。
    • 可见性是指,一个线程修改了被volatile修饰的变量后,其他线程可以立即发现新值。

    1.2 线程阻塞

    • synchronized可能会导致线程阻塞,因为它争夺资源时会让其他线程等待。
    • volatile不会引起阻塞,因为它不会影响线程的执行流程。

    1.3 依赖性与安全性

    • 当共享数据的改变依赖于其之前的值时,synchronized能保证线程安全,而volatile不适用于这种场景。
    • volatile主要用于标记完成或中断等场景,例如资源是否被释放或信号是否正确传递。

    1.4 修饰方式与重排序

    • synchronized修饰的是方法或代码块,而volatile修饰的是变量。
    • volatile修饰的变量不会被重排序,减少了同步有关的复杂性。

    1.5 虚拟机的规则

    • 从虚拟机的规则来看,volatile变量的写操作总是比后续的读操作先发生。这体现了内存的一致性模型。

    2. 使用易失性需要满足的条件

    2.1 单一修改-authority

    • 变量的修改不能依赖其当前值,并且只能有单一线程能够执行修改操作。

    2.2 不变约束

    • 变量不需要与其他变量完成不变式约束。例如,不需要保证 x + y = k 总是成立,除非这是非多线程环境下的绝对需求。

    2.3 无需额外锁定

    • 使用volatile时不需要额外的锁定机制,因为它不需要保护代码块的可执行性。

    3. 易失性特性在虚拟机层面的实现

    虚拟机通过以下机制确保易失性变量的一致性:

    • 当一个线程修改了被volatile修饰的变量时,其修改操作会立即反映到主内存中。
    • 其他线程在访问该变量时,会直接从主内存中读取当前值,而不是从工作内存中缓存副本。
    • 正常变量的读写操作可能因工作内存的缓存而遮蔽,容易导致多线程环境下的一致性问题。

    4. 易失性示例代码

    4.1 共享变量作为开关

    以下示例代码展示了volatile变量作为开关的应用:

    public class ValiableTest {    public static void main(String[] args) {        boolean isRunning = false;        Thread t1 = new Thread(() -> {            while (isRunning) {                System.out.println("运行中......");                try {                    Thread.sleep(100);                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });                new Thread(() -> {            isRunning = false;            System.out.println("下面终止运行");        }).start();                t1.start();    }}
    • volatile修饰:如果不使用volatileisRunning变量在多线程环境下可能不会更新,导致程序无法正常终止。
    • 使用volatile修饰:若isRunningvolatile修饰,主线程的修改会及时反映到其他线程,程序才能正常终止。

    总结

    通过对比synchronizedvolatile的特性,我们可以更好地理解它们各自适用的场景。synchronized更适合保护共享资源的原子性操作,而volatile则用以处理快速变更的状态标记,如资源释放或信号传递。在实际编码中,应该根据具体需求选择合适的机制。

    转载地址:http://kaxhz.baihongyu.com/

    你可能感兴趣的文章
    OpenCV与AI深度学习 | 基于Python和OpenCV将图像转为ASCII艺术效果
    查看>>
    OpenCV与AI深度学习 | 基于PyTorch实现Faster RCNN目标检测
    查看>>
    OpenCV与AI深度学习 | 基于PyTorch语义分割实现洪水识别(数据集 + 源码)
    查看>>
    OpenCV与AI深度学习 | 基于YOLO11的车体部件检测与分割
    查看>>
    OpenCV与AI深度学习 | 基于YoloV11自定义数据集实现车辆事故检测(有源码,建议收藏!)
    查看>>
    OpenCV与AI深度学习 | 基于YOLOv8 + BotSORT实现球员和足球检测与跟踪 (步骤 + 源码)
    查看>>
    OpenCV与AI深度学习 | 基于YOLOv8实现高级目标检测和区域计数
    查看>>
    OpenCV与AI深度学习 | 基于YOLOv8的停车对齐检测
    查看>>
    OpenCV与AI深度学习 | 基于YoloV8的药丸/片剂类型识别
    查看>>
    OpenCV与AI深度学习 | 基于YOLO和EasyOCR从视频中识别车牌
    查看>>
    OpenCV与AI深度学习 | 基于图像处理的火焰检测算法(颜色+边缘)
    查看>>
    OpenCV与AI深度学习 | 基于拉普拉斯金字塔实现图像融合(步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 基于机器视觉的磁瓦表面缺陷检测方案
    查看>>
    OpenCV与AI深度学习 | 基于深度学习的轮胎缺陷检测系统
    查看>>
    OpenCV与AI深度学习 | 如何使用YOLOv9分割图像中的对象
    查看>>
    OpenCV与AI深度学习 | 如何使用YOLOv9检测图片和视频中的目标
    查看>>
    OpenCV与AI深度学习 | 如何在 Docker 容器中使用 GPU
    查看>>
    OpenCV与AI深度学习 | 实战 | OpenCV中更稳更快的找圆方法--EdgeDrawing使用演示(详细步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | OpenCV传统方法实现密集圆形分割与计数(详细步骤 + 代码)
    查看>>
    OpenCV与AI深度学习 | 实战 | OpenCV实现扫描文本矫正应用与实现详解(附源码)
    查看>>