程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

Java高并发之volatile 关键字

发布于2021-03-13 13:25     阅读(734)     评论(0)     点赞(7)     收藏(5)


1、volatile简介

(1)volatile关键字只能修饰变量。
(2)volatile关键字是线程同步的轻量级实现,被volatile修饰的变量,具有可见性,即每次线程使用这个变量时,都是读取主内存中这个变量的最新值。
(3)同时被volatile修饰的变量还具有有序性,为了性能优化,jvm在不改变正确语义的情况下,会允许编译期和处理器对指令序列进行重新排序,而volatile可以阻止jvm重新排序。

Test test = new Test();

这行代码是分为三部执行的

1.为test分配内存空间;
2.初始化test;
3.将test指向分配的内存地址;

由于JVM有指令重排的特性,所有上述步骤可能为1->3->2,在逻辑上是可行的。如果线程A执行了1和3,线程B如果这时判断test是否有值,会得到有值的结果,但是使用test却会报错,因为test没有初始化。所有volatile可以组织指令重排,使之按照1->2->3的顺序执行。
(4)volatile可以保证变量的可见性,但是不能保证原子性。即多线程的情况不能保证线程安全,可能会出现脏读的情况。

2、Java内存模型

在这里插入图片描述
在当前的Java内存模型中,线程可以把变量保存为本地内存(如机器的寄存器)中,线程操作该变量时就是从本地内存中取值,而不是从主内存中取值,如果另一个线程在主内存中修改了这个变量的值,当前线程是感知不到的,会造成数据的不一致问题,也就是脏读
如果该变量使用了volatile修饰的话,那么线程每次操作该变量都会直接从主内存中读取数据、写入数据。让数据在线程间有可见性
在这里插入图片描述

3、为什么volatile能保证可见性,但是不能保证原子性

package com.kk.first.thread;

public class TestVolatile extends Thread {
	private static volatile Integer a = 0;
	@Override
	public void run() {
		int i = 0;
		while (i < 1000) {
			add();
			i++;
		}		
	}
	private static void add() {
		a++;
	}
	public static void main(String[] args) {
		TestVolatile tv = new TestVolatile();
		for (int i = 0; i < 10; i++) {
			Thread t = new Thread(tv);
			t.start();
		}
		try {
			Thread.sleep(10000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(a); // 7595
	}
}

如果volatile能保证原子性,那么执行结果a应为10000,但是结果却小于10000。所以volatile修饰的变量并不能保证原子性。虽然其修饰的变量是直接从主内存中读取数据,但是多个线程竞争的话,并且对数据有计算操作的话,如volatile修饰变量a在主内存中值为0,A线程读取的时候值为0,在A线程执行操作为加1,这时B线程也读取a的值,此时A线程执行的结果还没有写入到主内存中,所以B线程读取到的值为a=0,B线程也做+1操作。两个线程都执行完,将值写入主内存中。最终得到a的值为1,也就是两个线程都对a做的+1的操作,但是最后的结果却是a=1。

4、总结

所以volatile经常和synchronized关键字不是互斥的,是互补的,它们经常配合使用,比如通过双重检验锁实现线程安全的单例模式
详细可见这篇博文Volatile和Synchronized关键字实现单例模式(线程安全)
synchronized相关详解Java高并发之synchronized关键字



所属网站分类: 技术文章 > 博客

作者:天使的翅膀

链接:http://www.javaheidong.com/blog/article/114168/fe9fba1f18b311cd543e/

来源:java黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

7 0
收藏该文
已收藏

评论内容:(最多支持255个字符)