java volatile变量及其使用场景

2024-09-03 00:32

本文主要是介绍java volatile变量及其使用场景,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

java中的一种稍弱的同步机制,就是volatile变量,用于确保将变量的更新操作通知到其他线程。

变量声明为volatile后:

(1)编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序(重排序不懂的,可以自行百度,需要理解)。

(2)volatile变量不会被缓存在寄存器或对其他处理器不可见的地方

因此volatile变量总是会返回最新的值。

volatiel是比synchronize关键字更轻量级的同步机制,因为它不需要加锁,也就不会阻塞,所以性能会好点。

这边为了加深对volatile变量总能返回最新值的理解,你可以这样想:从内存可见性角度来看,写入volatile相当于推出同步代码块,而读取volatile变量就相当于进入同步代码块。

注意:并不建议过度依赖volatile变量提供的可见性。如果在代码中依赖volatile变量来控制状态的可见性,通常比使用锁的代码更脆弱,更难理解。

下面我来介绍一下volatile的使用场景,当且仅当满足以下所有条件时,才应该使用volatile变量:

(1) 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。

(2) 该变量不会与其他状态变量一起纳入不变性条件。

(3) 在访问变量时不需要加锁

可能你有点不好理解上面三句话的意思,我们一条一条来讲

对于第(1)条的理解就是:一般我们可能有这样的操作习惯,就是检查某个状态以判断是否退出循环,看一下下面这个示例,线程试图通过类似于数绵羊的传统方法进入休眠状态。为了使这个示例能正确执行,asleep必须为volatile变量。否则,当asleep被另一个线程修改时,执行判断的线程却发现不了。我们也可以用锁来确保asleep更新操作的可见性,但这将会使得代码变得更复杂。什么叫 对变量的写入操作不依赖变量的当前值?就如示例1中decide该函数中对asleep先判断后执行(执行中保包含了对变量的改变),这种情况下没使用锁,所以可能在多线程情况下,alseep的内存可见性得不到保证。对于这类“对变量的写入操作依赖变量的当前值”的操作,是需要用锁进行保护的,此时可以考虑用内置锁或者显示锁,但是方便起见可以使用volatile来保护asleep这个变量。毕竟只是想保护一个变量。解决方式如示例2,当然该示例对上述第三个条件同样满足。那条件2中“该变量不会与其他状态一起纳入不变性条件”是什么意思呢?就是volatile变量不能与其他共享变量做复合操作,volatile变量本身在没有锁保护的情况下也不能做复合操作(这是我的理解)。

 

示例1:

public class NoVolatile {private int sheepCount;private boolean asleep;public void decide() {while (! asleep) {countSomeSheep();}}public void setAsleep() {asleep = true;}private void countSomeSheep() {if (sheepCount < 1000) {sheepCount++;} else {sheepCount = 0;setAsleep();}}
}

示例2:

class VolatileDemo {private volatile asleep;public void decide() {while (! asleep) {countSomeSheep();}}public void setAsleep() {asleep = true;}
}

对于volatile变量的使用需要有以下注意点:

加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性。啥意思呢,就是,volatile的语义不足以确保递增操作(count++)的原子性,除非你能确保只有一个线程对变量执行写操作。

 

 

这篇关于java volatile变量及其使用场景的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1131509

相关文章

Java图片压缩三种高效压缩方案详细解析

《Java图片压缩三种高效压缩方案详细解析》图片压缩通常涉及减少图片的尺寸缩放、调整图片的质量(针对JPEG、PNG等)、使用特定的算法来减少图片的数据量等,:本文主要介绍Java图片压缩三种高效... 目录一、基于OpenCV的智能尺寸压缩技术亮点:适用场景:二、JPEG质量参数压缩关键技术:压缩效果对比

Java调用C++动态库超详细步骤讲解(附源码)

《Java调用C++动态库超详细步骤讲解(附源码)》C语言因其高效和接近硬件的特性,时常会被用在性能要求较高或者需要直接操作硬件的场合,:本文主要介绍Java调用C++动态库的相关资料,文中通过代... 目录一、直接调用C++库第一步:动态库生成(vs2017+qt5.12.10)第二步:Java调用C++

springboot+dubbo实现时间轮算法

《springboot+dubbo实现时间轮算法》时间轮是一种高效利用线程资源进行批量化调度的算法,本文主要介绍了springboot+dubbo实现时间轮算法,文中通过示例代码介绍的非常详细,对大家... 目录前言一、参数说明二、具体实现1、HashedwheelTimer2、createWheel3、n

使用Python实现一键隐藏屏幕并锁定输入

《使用Python实现一键隐藏屏幕并锁定输入》本文主要介绍了使用Python编写一个一键隐藏屏幕并锁定输入的黑科技程序,能够在指定热键触发后立即遮挡屏幕,并禁止一切键盘鼠标输入,这样就再也不用担心自己... 目录1. 概述2. 功能亮点3.代码实现4.使用方法5. 展示效果6. 代码优化与拓展7. 总结1.

使用Python开发一个简单的本地图片服务器

《使用Python开发一个简单的本地图片服务器》本文介绍了如何结合wxPython构建的图形用户界面GUI和Python内建的Web服务器功能,在本地网络中搭建一个私人的,即开即用的网页相册,文中的示... 目录项目目标核心技术栈代码深度解析完整代码工作流程主要功能与优势潜在改进与思考运行结果总结你是否曾经

Java利用docx4j+Freemarker生成word文档

《Java利用docx4j+Freemarker生成word文档》这篇文章主要为大家详细介绍了Java如何利用docx4j+Freemarker生成word文档,文中的示例代码讲解详细,感兴趣的小伙伴... 目录技术方案maven依赖创建模板文件实现代码技术方案Java 1.8 + docx4j + Fr

SpringBoot首笔交易慢问题排查与优化方案

《SpringBoot首笔交易慢问题排查与优化方案》在我们的微服务项目中,遇到这样的问题:应用启动后,第一笔交易响应耗时高达4、5秒,而后续请求均能在毫秒级完成,这不仅触发监控告警,也极大影响了用户体... 目录问题背景排查步骤1. 日志分析2. 性能工具定位优化方案:提前预热各种资源1. Flowable

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat