Java多线程并发编程 Volatile关键字
发布时间 - 2026-01-11 01:14:27 点击率:次volatile 关键字是一个神秘的关键字,也许在 J2EE 上的 JAVA 程序员会了解多一点,但在 Android 上的 JAVA 程序员大多不了解这个关键字。只要稍了解不当就好容易导致一些并发上的错误发生,例如好多人把 volatile 理解成变量的锁。(并不是)

volatile 的特性:
具备可见性
保证不同线程对被 volatile 修饰的变量的可见性。
有一被 volatile 修饰的变量 i,在一个线程中修改了此变量 i,对于其他线程来说 i 的修改是立即可见的。
如:
volatile int i = 0;// 语句 1 i++; // 语句 2
语句 2 执行完后,i 最新的值会立即被强制更新到主内存(共享内存),并通知其他缓存了 i 的线程,令其他线程的工作内存里的 i 失效,从而需重新到主内存读取最新的值。
具备有序性
被 volatile 修饰的变量,不会被优化排序。
解决的问题详见:Java 多线程并发编程 并发三大要素 的 三、有序性。
当编译器在给程序优化排序时,若遇到 volatile 变量的读操作或者写操作,则会保证在其前面的操作全部进行完成,且结果对后面的操作可见;并且保证在其后面的操作没有进行。
不具备原子性
volatile 不具备原子性,所以它是线程不安全的。
实验:
// 一个单例的实现
public class SingletonTest {
private static volatile SingletonTest mInstance = null;
private SingletonTest() {}
public static SingletonTest getInstance() {
if (mInstance == null) {
mInstance = new SingletonTest();
System.out.println(" 初始化完成 ");
}
return mInstance;
}
}
// 测试代码
public class Test {
public static void main(String[] var0) {
for(int i = 0; i < 20; i++){
ThreadTest test = new ThreadTest();
test.start();
}
}
static class ThreadTest extends Thread{
@Override
public void run() {
super.run();
SingletonTest.getInstance();
}
}
}
结果:
每次运行都输出多个 “初始化完成”。
volatile 的解释
下面这段话摘自《深入理解 Java 虚拟机》:
“观察加入 volatile 关键字和没有加入 volatile 关键字时所生成的汇编代码发现,加入 volatile 关键字时,会多出一个 lock 前缀指令”
被 volatile 修饰的变量进行读和写操作的时候,在相应的汇编程序中都会多一句内存屏障(Memory Barrier)。
而这个 lock 就是内存屏障。
内存屏障的作用:
1、在重新优化排序时保证其后面的指令不会被排到内存屏障的前面,前面的指令也不会排到内存屏障的后面。- 有序性
2、强制对写操作后的结果(立即)刷新到主内存。
3、刷新结果到主内存时,通知并令其他线程缓存内的值过期 / 失效。
2 和 3 合起来则是可见性。
说到这里,也许会有好多人困惑,既然可见性可以保证,既然可以做到修改某个变量的值后,会刷新到主内存,并令其他线程缓存失效,为什么不能保证原子性呢?这也是我之前走进的一个困区。
继续用 i++ 来分析一下,这里面包含的指令:
从主内存读取到缓存 // 指令 1
进行运算 // 指令 2
从缓存刷新到主内存 // 指令 3
内存屏障 // 指令 4
虽然指令 4(内存屏障)功能强大,但可惜 // 指令 1、2、3 都不是具备原子性,所以导致 volatile 不具备原子性,线程不安全,不能替代锁的作用。
使用场景
如一些简单的状态标记:
volatile boolean inited = false;
// 线程 1
init(); // 语句 1
inited = true; // 语句 2
// 线程 2
while(inited){
work(); // 语句 3
}
1、可确保语句 1 和语句 2 的执行顺序。
2、可确保执行语句 2 后,线程 2 可立即获取到最新的修改,从而执行语句 3。
# Java
# Volatile
# 关键字
# Java并发编程之常用的多线程实现方式分析
# Java多线程并发编程和锁原理解析
# 深入理解Java多线程与并发编程
# Java多线程并发编程(互斥锁Reentrant Lock)
# Java多线程之并发编程的核心AQS详解
# 不具备
# 见性
# 不安全
# 新到
# 是一个
# 汇编程序
# 有一
# 会有
# 一句
# 多个
# 则是
# 就好
# 但在
# 三大
# 说到
# 它是
# 不了解
# 这里面
# 多出
# 则会
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
b2c电商网站制作流程,b2c水平综合的电商平台?
Laravel Blade模板引擎语法_Laravel Blade布局继承用法
js实现获取鼠标当前的位置
香港代理服务器配置指南:高匿IP选择、跨境加速与SEO优化技巧
想要更高端的建设网站,这些原则一定要坚持!
为什么要用作用域操作符_php中访问类常量与静态属性的优势【解答】
百度输入法ai组件怎么删除 百度输入法ai组件移除工具
悟空浏览器如何设置小说背景色_悟空浏览器背景色设置【方法】
Edge浏览器提示“由你的组织管理”怎么解决_去除浏览器托管提示【修复】
html文件怎么打开证书错误_https协议的html打开提示不安全【指南】
如何在腾讯云免费申请建站?
Android GridView 滑动条设置一直显示状态(推荐)
如何在万网自助建站平台快速创建网站?
html5的keygen标签为什么废弃_替代方案说明【解答】
如何在Windows服务器上快速搭建网站?
怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?
黑客如何通过漏洞一步步攻陷网站服务器?
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
如何续费美橙建站之星域名及服务?
文字头像制作网站推荐软件,醒图能自动配文字吗?
东莞专业网站制作公司有哪些,东莞招聘网站哪个好?
Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能
Android使用GridView实现日历的简单功能
百度浏览器如何管理插件 百度浏览器插件管理方法
php后缀怎么变mp4格式错误_修改扩展名提示格式不对怎么办【技巧】
Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权
Laravel如何使用模型观察者?(Observer代码示例)
Laravel如何创建自定义Facades?(详细步骤)
如何用西部建站助手快速创建专业网站?
公司网站制作需要多少钱,找人做公司网站需要多少钱?
青岛网站建设如何选择本地服务器?
Python进程池调度策略_任务分发说明【指导】
如何用wdcp快速搭建高效网站?
Laravel怎么连接多个数据库_Laravel多数据库连接配置
Laravel如何与Inertia.js和Vue/React构建现代单页应用
Laravel怎么实现一对多关联查询_Laravel Eloquent模型关系定义与预加载【实战】
Laravel如何配置Horizon来管理队列?(安装和使用)
JavaScript实现Fly Bird小游戏
Laravel如何监控和管理失败的队列任务_Laravel失败任务处理与监控
为什么php本地部署后css不生效_静态资源加载失败修复技巧【技巧】
Laravel如何实现邮箱地址验证功能_Laravel邮件验证流程与配置
南京网站制作费用,南京远驱官方网站?
Laravel Seeder怎么填充数据_Laravel数据库填充器的使用方法与技巧
Linux安全能力提升路径_长期防护思维说明【指导】
如何在万网开始建站?分步指南解析
1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤
今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】
linux写shell需要注意的问题(必看)
Laravel中间件起什么作用_Laravel Middleware请求生命周期与自定义详解
Laravel Eloquent访问器与修改器是什么_Laravel Accessors & Mutators数据处理技巧

