0

0

在Java里原子性可见性有序性如何理解_Java并发特性解析

P粉602998670

P粉602998670

发布时间:2026-01-30 13:50:14

|

317人浏览过

|

来源于php中文网

原创

Java并发中原子性、可见性、有序性是保障共享变量操作正确的三层约束,共同构成happens-before规则基础;volatile提供可见性与部分有序性但不保证原子性,synchronized三者兼具,AtomicInteger通过CAS融合三者。

在java里原子性可见性有序性如何理解_java并发特性解析

Java 并发中的原子性、可见性、有序性不是并列的三个独立概念,而是围绕「多线程环境下对共享变量操作的行为约束」形成的三层保障——其中原子性解决“执行不中断”,可见性解决“改了别人看不看得见”,有序性解决“代码写的顺序和实际执行顺序是否一致”。它们共同构成 happens-before 规则的基础,而 happens-before 才是真正用来推理正确性的工具

原子性 ≠ 单条语句不拆分,而是「不可分割的执行单元」

很多人以为 i++ 是原子的,其实它被编译为「读取 i → 加 1 → 写回 i」三步,中间可被线程抢占。即使 int 类型的读写在 JVM 层面通常是原子的(对 32 位变量),但复合操作仍不安全。

  • AtomicInteger.incrementAndGet() 是原子的,因为底层用 CAS(Compare-And-Swap)指令保证整个操作不可中断
  • synchronized 块或 ReentrantLock 也能提供原子性,但粒度更大、开销更高
  • longdouble 的非 volatile 读写,在 32 位 JVM 上可能不是原子的(JVM 规范允许分两次 32 位操作)

可见性失效常见于「线程本地缓存未及时同步」

每个线程有自己的工作内存(比如 CPU 寄存器或 L1/L2 缓存),对共享变量的修改可能只停留在本地,其他线程看不到最新值。这不是 bug,而是 JVM 为性能做的默认优化。

  • volatile 强制每次读都从主内存取,每次写都立即刷到主内存,从而保证可见性
  • synchronized 在解锁前会把工作内存中变量的最新值刷新到主内存,加锁时会清空本地缓存并从主内存读取——所以它也具备可见性保障
  • 仅靠 final 字段能保证初始化完成后的可见性(构造器内写入的 final 值,其他线程看到对象引用后一定能看见该值),但不适用于后续修改
  • 没有同步机制时,哪怕只是 flag = true 这种简单赋值,另一个线程也可能永远看不到 true

有序性被重排序打破,但 happens-before 定义了哪些重排被禁止

JVM 和 CPU 都可能对指令重排序(包括编译器重排、运行期重排、内存系统重排),只要不改变单线程语义。但多线程下,这种重排可能导致诡异结果。

Grokipedia
Grokipedia

xAI推出的AI在线百科全书

下载

立即学习Java免费学习笔记(深入)”;

  • volatile 写之前的所有操作,不能被重排到写之后;volatile 读之后的所有操作,不能被重排到读之前——这就是「volatile 的禁止重排语义」
  • synchronized 的解锁操作 happens-before 后续任意线程对该锁的加锁操作,天然构成有序性边界
  • 构造器中对 final 字段的写入,happens-before 构造器结束,因此其他线程看到该对象引用时,必能看到正确的 final 值
  • 不要依赖「代码写在前面就一定先执行」——比如 a = 1; flag = true; 中,flag = true 可能先于 a = 1 对其他线程可见,除非加 volatile 或锁

真正容易被忽略的是:这三个特性从来不会单独起作用。一个 volatile 变量既提供可见性,也提供部分有序性(但不提供原子性);synchronized 同时提供原子性、可见性和有序性;而 AtomicIntegercompareAndSet() 方法之所以可靠,是因为它内部融合了 volatile 读写 + CAS,同时满足三者要求。写并发逻辑时,别问“我需要哪个特性”,而要问“我这个场景下,哪些操作必须构成一个 happens-before 关系”。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

463

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

544

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

113

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

200

2025.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

113

2025.08.29

C++中int、float和double的区别
C++中int、float和double的区别

本专题整合了c++中int和double的区别,阅读专题下面的文章了解更多详细内容。

102

2025.10.23

c++中volatile关键字的作用
c++中volatile关键字的作用

本专题整合了c++中volatile关键字的相关内容,阅读专题下面的文章了解更多详细内容。

69

2025.10.23

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

523

2023.08.10

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

0

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 8万人学习

Java 教程
Java 教程

共578课时 | 53.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号