java并发关键字_关于java并发编程关键字volatile?

带你理解一下volatile关键字

回顾之前Java内存模型特征可以了解到该模型是围绕着并发过程中如何处理原子性、可见性和有序性这三个特征来建立的。

原子性:一个操作或多个操作要么全部执行完成且执行过程不被中断,要么就不执行。Java内存模型来直接保证的原子性变量操作包括read、load、assign、use、store和write这六个,如果应用场景需要更大范围的原子性保证,Java内存模型还提供了lock和unlock操作来满足需求,比如synchronize关键字。在synchronize块之间的操作就具备原子性。

可见性:指当一个线程修改了共享变量的值,其它线程能够立即得知这个修改。Java内存模型是通过在变量修改后将新值同步回主内存,在变量读取前从主内存刷新变量值这种依赖主内存作为传递媒介的方式来实现可见性的。

有序性:在本线程内,所有操作都是有序的,即按照代码先后顺序执行;如果在一个线程观察另一个线程,所有操作都是无序的,因为有“指令重排序”现象和“工作内存与主内存同步延迟”现象。

了解上述并发处理三大特性之后,再看volatile关键字,该关键字满足可见性和有序性,所以在Java中能提供最轻量级的同步机制。

volatile可见性:volatile的规则保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。因此volatile保证了多线程操作变量的可见性。

volatile有序性:使用volatile修饰的变量会禁止指令重排序,JVM中对不是原子性的操作会进行重排序的优化,只要不影响最终计算结果。例如:

// 线程1中

{

...

obj= getObject(); // 步骤1

isRegister = true; // 步骤2

...

}

// 线程2中

{

...

if (isRegister) { // 步骤3,依赖步骤2的值

fun(obj); // 步骤4,依赖步骤1的值

}

...

}

上述代码中,线程1中的代码步骤1和步骤2可能出现重排序的情况,因为对线程1来说顺序打乱不影响线程1自己的运算结果,但是对线程2来说,如果线程1中的步骤2先执行,最终就无法得到正确的结果。

volatile修饰的变量,在读取或者写入的前后都会插入内存屏障来达到禁止重排序的效果,进而保证有序性。

volatile不能保证原子性,因此不能完全达到线程安全效果,除非满足一下条件:运算结果不依赖当前值,或者能够确保只有单一的线程修改该变量的值。

变量不需要与其他状态变量共同参与不变约束。

比如volatile修饰的变量count出现count++、count+1等非原子操作,就无法确保线程安全。

import java.io.*;

class test

{

private static final int THREAD_COUNT = 20;

public static volatile int race = 0;

public static void increase () {

race++;

}

public static void main (String[] args) throws java.lang.Exception

{

System.out.println("hi");

for (int i = 0; i < THREAD_COUNT; i++) {

new Thread(new Runnable() {

@Override

public void run() {

for (int j = 0; j < 1000; j++) {

increase();

}

}

}).start();

}

while (Thread.activeCount() > 1) {

Thread.yield();

}

System.out.println("race = "+ race);

}

}

运行结果:

hi

race = 19902

注意,测试的结果跟环境有关,有的测试环境可能结果出现正确的情况,可以将测试数据改大一点。本人测试时,开始选择10个线程,然后只累加10次,测试下来发现结果都是正确的~

另外大家可能会疑惑volatile不是保证变量的可见性了吗?一旦被修改会立即同步到主内存中,确保其它线程都拿到最新数据。这里可以这样理解,比如线程1和线程2都拿到最新volatile修饰的变量count = 10,当count++时,由于不是原子操作,当线程1还在执行加加指令时,线程2已经将count数据11更新到主存了,此时对于线程1来说,数据已经过时了,等线程1执行完时,又将11同步到主存,结果导致两个线程都执行count++,但是最终结果却小于正常值。

Python网络爬虫与推荐算法新闻推荐平台:网络爬虫:通过Python实现新浪新闻的爬取,可爬取新闻页面上的标题、文本、图片、视频链接(保留排版) 推荐算法:权重衰减+标签推荐+区域推荐+热点推荐.zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值