专业的JAVA编程教程与资源

网站首页 > java教程 正文

Java 内存模型与并发编程中的可见性、原子性、有序性有啥关联

temp10 2025-10-14 05:14:08 java教程 2 ℃ 0 评论

Java 内存模型(JMM)概述

Java 内存模型(JMM)精准地定义了 Java 虚拟机在多线程环境下对共享变量进行读写操作的规则。它通过对内存操作(诸如 read、write、lock、unlock 等)进行细致规范,有效解决了处理器缓存一致性的问题,从而确保不同线程能够准确无误地获取共享变量的最新值。

JMM 与并发三大特性

可见性

可见性指的是,当一个线程对共享变量进行修改时,另一个线程能够立即感知到这一变化。JMM 借助内存屏障,并遵循 Happens - Before 原则,为可见性提供了坚实保障。

Java 内存模型与并发编程中的可见性、原子性、有序性有啥关联

原子性

原子性意味着一个操作具有不可中断的特性,它要么完整地执行成功,要么完全不执行。JMM 确保了基本的读写操作具备原子性;而对于更为复杂的原子性需求,则需要借助锁机制来实现。

有序性

有序性要求程序的执行顺序与代码的编写顺序保持一致。尽管 JMM 允许指令重排序,但它会严格保证在 Happens - Before 关系下的有序性。

volatile 关键字

底层原理

volatile 关键字通过插入内存屏障的方式,确保了可见性和有序性。当对一个 volatile 变量进行写操作时,JMM 会在写操作之后插入一个写屏障,将工作内存中对该变量的修改刷新到主内存;当读取一个 volatile 变量时,JMM 会在读操作之前插入一个读屏障,使工作内存中对应的变量失效,进而强制从主内存重新读取该变量的值。同时,volatile 关键字禁止了指令重排序。

应用场景

volatile 关键字适用于状态标记量(例如 boolean 类型的 flag)以及双重检查锁定(Double - Checked Locking)中的单例模式(此时需结合 final 关键字来保证有序性)。然而,它无法保证复合操作(如 i++)的原子性。

synchronized 关键字

底层原理

synchronized 作为 Java 语言层面的重要关键字,其底层基于 JVM 的管程(Monitor)机制构建。它能够全方位保障并发编程中的可见性、原子性和有序性。当线程尝试获取锁时,会将工作内存清空,随后从主内存中重新读取共享变量;而当线程释放锁时,又会把工作内存中对共享变量所做的修改刷新至主内存。此外,synchronized 具备排他性,在同一时刻,仅允许一个线程执行被其修饰的代码块或方法。JVM 为了优化锁的使用效率,会对 synchronized 进行锁升级操作,遵循从偏向锁到轻量级锁,再到重量级锁的升级路径。

应用场景

synchronized 适用于对共享资源进行互斥访问的场景,因其使用方式简单便捷而被广泛应用。然而,它也存在一定的局限性,锁粒度固定,且不支持中断操作,也无法设置超时机制。

ReentrantLock 类

底层原理

ReentrantLock 是
java.util.concurrent.locks 包下的一个类,它基于 AQS(
AbstractQueuedSynchronizer)框架实现。AQS 精心维护着一个先进先出(FIFO)的等待队列以及状态变量,通过 CAS(Compare - And - Swap)操作对状态进行修改,进而实现锁的获取与释放。相较于 synchronized,ReentrantLock 提供了更为强大的功能,比如支持可中断锁、可选择公平锁或非公平锁模式,还具备条件变量(Condition)机制。

应用场景

当需要对锁进行更细粒度的控制,或是希望以非阻塞的方式获取锁,亦或是需要定时尝试获取锁,又或者面临多条件等待的情况时,ReentrantLock 会是更优的选择。例如,在生产者 - 消费者模型中,当需要处理等待队列满或空的情况时,ReentrantLock 能够发挥出其独特的优势。



本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表