`
josico
  • 浏览: 43111 次
社区版块
存档分类
最新评论

volatile关键字实例分析

阅读更多

volatile关键字相信大家都不陌生,在多线程并发编程里面用的比较多。网上有很多分析,但到底用和不用有什么区别,会造成什么影响,实际的代码示例比较少。现在就用代码来针对分析一下

引用linux之父Torvalds的一句话 -- talk is cheap show me the code

 

程序思路如下,先让thread2跑起来,进入一个循环,而这个循环也不是严格意义上的死循环,只不过解开死循环的key不在该线程本身,而是被另一个线程控制着。而这里的key有2个,一个是加了volatile,一个是没加,会有什么效果呢?运行下看看先(哇塞,用了句倒装惊讶

 

package com.cug.thread;

class VolatileExample {
	int x = 0;
	volatile int b = 0;

	private void write() {
		x = 5;
		b = 1;
	}

	private void read() {
		while (x != 5) {
		}
		/*while (b != 1) {
		}*/
	}

	public static void main(String[] args) throws Exception {
		final VolatileExample example = new VolatileExample();
		Thread thread1 = new Thread(new Runnable() {
			public void run() {
				try {
					//确保Thread2在Thread1之前执行
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				example.write();
			}
		});

		Thread thread2 = new Thread(new Runnable() {
			public void run() {
				example.read();
			}
		});
		
		thread2.start();
		thread1.start();
	}
}

 

执行完了,大家会发现,当用x作为key的时候,不顶事儿,还是死循环。但用b作为key的时候,循环很快被解开,得到了我们预计的效果。

好了,有了实例,我们再带着问题好好分析。

 

首先我们需要简单说明一下java内存模型(java memory model)

根据Java Language Specification中的说明, jvm系统中存在一个主内存(Main Memory或Java Heap Memory),Java中所有变量都储存在主存中,对于所有线程都是共享的。

 

每条线程都有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作都是在工作内存中进行,线程之间无法相互直接访问,变量传递均需要通过主存完成。

 java内存模型

Java语言规范中也有指出:为了获得最佳速度,允许线程保存共享成员变量的私有拷贝,而且只当线程进入或者离开同步代码块时才将私有拷贝与共享内存中的原始值进行比较。

 

通俗点说就是,这里的2个变量

int x = 0;
volatile int b = 0;

x位于工作内存中,而b位于主存中。

再通俗点讲就是,thread1有一个自己的x,thread2有一个自己的x,而他们只有一个共享的b 

 

很多人拿volatile和synchronzed说事,比较效率啊什么的,其实这有什么好比的,两个人负责的功能点都不一样。有的地方可能确实可以用volatile代替synchronized,也确实能提升一些效率,但你有考虑过你代码的可读性吗?不要为了一时的效率,而牺牲别人对你代码意思的误解。(之前看过一个人写了个for循环,循环了50000次,问他干嘛这么写,他说他为了让程序在这稍微停一会)。

好了好了,不跑题,我们接着说

synchronized是同步的意思,同步代码块,同步函数等,意思就是让一小块独立成一个单元来执行。

 

而volatile呢,它的作用其实就是一个共享操作、集中管理的作用。不知道大家有没有看过火影,火影里面有一个Team很厉害叫佩恩(又快跑了。。),他是由6个人组成的,他有一个特殊点就是6个人可以交换视野,每个人都能看到另外5个人看到的东西。volatile扮演的就是这么一个视野的作用,共享属性,同步更新。对加了volatile关键字的属性,不会被加载到每个线程的工作内存中,而是在主存中修改查看

 

如有说的不好的不全的,大家可以到这里去看看,感觉这个还是很权威啊,我的只能叫小众,看合不合您的胃口了大笑

  • 大小: 9.7 KB
分享到:
评论
1 楼 shj189 2014-04-28  
 

相关推荐

    C#中volatile与lock用法

    本文实例讲述了C#中volatile与lock用法,分享给大家供大家参考。具体分析如下: 一、C#中volatile volatile是C#中用于控制同步的关键字,其意义是针对程序中一些敏感数据,不允许多线程同时访问,保证数据在任何访问...

    93个netty高并发教学视频下载.txt

    83_AtomicIntegerFieldUpdater实例演练与volatile关键字分析;84_Netty引用计数注意事项与内存泄露检测方式;85_Netty编解码器剖析与入站出站处理器详解;86_Netty自定义编解码器与TCP粘包拆包问题;87_Netty编解码...

    精通并发与netty视频教程(2018)视频教程

    83_AtomicIntegerFieldUpdater实例演练与volatile关键字分析 84_Netty引用计数注意事项与内存泄露检测方式 85_Netty编解码器剖析与入站出站处理器详解 86_Netty自定义编解码器与TCP粘包拆包问题 87_Netty编解码器...

    精通并发与 netty 视频教程(2018)视频教程

    Netty引用计数的实现机制与自旋锁的使用技巧 82_Netty引用计数原子更新揭秘与AtomicIntegerFieldUpdater深度剖析 83_AtomicIntegerFieldUpdater实例演练与volatile关键字分析 84_Netty引用计数注意事项与内存泄露...

    精通并发与netty 无加密视频

    第83讲:AtomicIntegerFieldUpdater实例演练与volatile关键字分析 第84讲:Netty引用计数注意事项与内存泄露检测方式 第85讲:Netty编解码器剖析与入站出站处理器详解 第86讲:Netty自定义编解码器与TCP粘包拆包...

    嵌入式Linux C编程入门(第2版) PPT

    2.2.3 vi的使用实例分析 40 2.3 嵌入式linux编译器gcc的使用 41 2.3.1 gcc概述 41 2.3.2 gcc编译流程分析 42 2.3.3 gcc警告提示 45 2.3.4 gcc使用库函数 47 2.3.5 gcc代码优化 49 2.4 嵌入式...

    javaSE代码实例

    16.6 volatile关键字的含义与使用 372 16.7 小结 373 第17章 高级线程开发 374 17.1 线程池的使用 374 17.1.1 线程池的基本思想 374 17.1.2 JavaSE 5.0中固定尺寸线程池的基本知识 374 17.1.3 自定义...

    c#学习笔记.txt

    volatile指示字段可由操作系统、硬件或并发执行的线程等在程序中进行修改。 9,语句 语句是程序指令。除非特别说明,语句都按顺序执行。C# 具有下列类别的语句。 类别C# 关键字 选择语句if, else, switch, case 迭代...

    Visual C++音频/视频处理技术及工程实践 (分卷1)

    2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 2.9 ...

    -C++参考大全(第四版) (2010 年度畅销榜

    4.9 棋盘游戏实例 第5章 指针 5.1 什么是指针 5.2 指针变量 5.3 指针运算符 5.4 指针表达式 5.5 指针和数组 5.6 多级间址 5.7 初始化指针 5.8 指向函数的指针 5.9 C语言的动态分配函数 5.10 指针应用中的问题 第6...

    宋劲彬的嵌入式C语言一站式编程

    3. 算法的时间复杂度分析 4. 归并排序 5. 线性查找 6. 折半查找 12. 栈与队列 1. 数据结构的概念 2. 堆栈 3. 深度优先搜索 4. 队列与广度优先搜索 5. 环形队列 13. 本阶段总结 II. C语言本质 14. 计算机中数的表示 1...

    Visual C++音频视频处理技术及工程实践(含源码2/2)

    2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 ...

    Visual C++音频视频处理技术及工程实践(分卷0)

    2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 2.9 ...

    Visual C++ 音频/视频 处理技术及工程实践(分卷3)

    2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 2.9 ...

    Visual C++音频视频处理技术及工程实践(分卷9)

    2.8.1 如何使用volatile和const_cast 86 2.8.2 如何构造unicode版本的程序 87 2.8.3 如何使用.def文件 87 2.8.4 如何正确编写Win32 DLL 87 2.8.5 如何编写和使用资源DLL 88 2.8.6 如何实现对话框的数据交换 88 2.9 ...

Global site tag (gtag.js) - Google Analytics