java 线程Thread 技术--volatile关键字
java 语言中允许线程访问共享变量,为了保证共享变量能被准确和一致的更新,Java 语言提供了volatile 关键字,也就是我们所说的内存一致性;
问题抛出:(尝试去运行下面代码,以及将volatile 加上的运行结果)
/**
* 问题抛出
* @param args
*/
public class Volatile01 { public /*volatile*/ boolean flag = true; public static void main(String[] args) throws InterruptedException {
Volatile01 v =new Volatile01();
RunV r =new RunV(v);
Thread th =new Thread(r);
th.start(); //在main method to modify flag
Thread.sleep(1000);
v.flag=false;
} } class RunV implements Runnable{
Volatile01 vola ;
RunV(Volatile01 vola){
this.vola=vola;
} @Override
public void run() {
//
while(vola.flag) {} System.err.println("flag 状态转变"); } }
问题的原因是是什么呢?
根据上面的运行结果,在没有volatile 关键字的情况下,运行结果是:线程持续陷入死循环状态,flag 并没有改变;
加上volatile 后 运行结果:flag 状态转变,说明flage 已经被改变了;
请看:http://www.infoq.com/cn/articles/ftf-java-volatile 这篇文章,我大致的说一下:主要跟处理器有关,处理器为了运行的效率,不直接跟内存进行通讯;
它是先将内存的数据先读取到cpu 内部缓存(L1,L2,其他)中,操作完之后不知道什么时候才会将数据重新写到内存来修改内存中存在的值,所以在上面的例子中
在修改了flage =true 后,RunV线程是无法感知到的,依然是cpu 缓存的值;
volatile如何保证可见性呢?
依然看上文的那篇文章;里面由一些图文解释;
volatile保证原子性操作吗?是否能解决数据不一致的问题(尝试多运行如下代码,可以得到都不同的结果)?
/**
* volaile 是否支持原子性操作
* @param args
*/
public class Volatile02 { public volatile int v=0; public static void main(String[] args) throws InterruptedException, ExecutionException {
Volatile02 v =new Volatile02();
RunB r =new RunB(v);
List<Thread> theads =new ArrayList<Thread>();
for(int i=0;i<10;i++) {
theads.add(new Thread(r));
} theads.forEach((t->{
t.start();
})); theads.forEach((t->{
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
})); System.out.println(v.v);
} } class RunB implements Runnable{
Volatile02 vola ;
RunB(Volatile02 vola){
this.vola=vola;
} @Override
public void run() {
for(int i=0;i<10000;i++) { vola.v++;
System.out.println(Thread.currentThread().getName());
} } }
运行得知,volatile 尽管保证了内存的可见性,但并不能保证多线程下的原子操作导致数据不一致问题;只能靠synchronized 和lock;
java 线程Thread 技术--volatile关键字的更多相关文章
- java线程学习之volatile关键字
volatile变量的主要作用:是使变量在多个线程间可见. 在java中每一个线程都会有一块工作内存区,其中存放着所有线程共享的主内存的变量值的拷贝.当线程执行时,它在自己的工作内存区操作这些变量,为 ...
- java 线程Thread 技术--线程状态与同步问题
线程技术第三篇: 线程的状态: 1. 创建状态: 当用new 操作符创建一个新的线程对象时,该线程就处于创建状态,系统不为它分配资源 2.可运行状态:当线程调用start 方法将为线程分配必须的系统资 ...
- java 线程Thread 技术--1.5 Executor Executors,ThreadPool,Queue
Executors : Executors ,就是一个线程工具类:大部分操作线程的方法,都可以在这个工具类中就行创建,执行,调用一些线程的方法: Executor : 用于执行和提交一个runnabl ...
- java 线程Thread 技术--1.5 Future与Callable
Callable: 从官方文档说起: 通过实现callable 的called 方法可以使一个任务可以返回一个结果以及可能抛出一个异常: callable 与runnable 是相似的,可以被其他线程 ...
- java 线程Thread 技术--1.5Lock 与condition 演示生产者与消费模式
在jdk 1.5 后,Java 引入了lock 锁来替代synchronized ,在使用中,lock锁的使用更加灵活,提供了灵活的 api ,不像传统的synchronized ,一旦进入synch ...
- java 线程Thread 技术--方法演示生产与消费模式
利用wait 与notifyAll 方法进行演示生产与消费的模式的演示,我们两个线程负责生产,两个线程消费,只有生产了才能消费: 在effective Java 中有说过: 1. 在Java 中 ,使 ...
- java 线程Thread 技术--线程创建源码解释
永远不要忘记最基础的东西,只有把最基础的知识打牢靠,才能够使你走的更远,我将从今天开始,进行线程知识的回顾,一些常用知识点,以及java1.5 引入的并发库,进行详细的讲解与总结 创建线程的目的是为了 ...
- java 线程Thread 技术--线程方法详解
Thread 类常用的方法与Object类提供的线程操作方法:(一个对象只有一把锁
- java 线程Thread 技术--创建线程的方式
在第一节中,对线程的创建我们通过看文档,得知线程的创建有两种方式进行实现,我们进行第一种方式的创建,通过继承Thread 类 ,并且重写它的run 方法,就可以进行线程的创建,所有的程序执行都放在了r ...
随机推荐
- websocket 11
1. websocket 回顾: - 什么是轮训? - 通过定时器让程序每隔n秒执行一次操作. - 什么是长轮训? - 浏览器向后端发起请求,后端会将请求 hang 住,最多hang 30s. 如果一 ...
- Javascript 来判断数组的假值如 null false "" NaN
Javascript 来判断数组的假值如 null false "" NaN function bouncer(arr) { arr = arr.filter(function(a ...
- <亲测>CentOS中yum安装ffmpeg
CentOS中yum安装ffmpeg 1.升级系统 sudo yum install epel-release -y sudo yum update -y sudo shutdown -r now 2 ...
- new 对象时的暗执行顺序
为什么称为暗执行顺序,因为当我们在new 对象时,其不是简简单单的new一个完事,它要首先检查父类的,静态的,非静态的等代码,就好像我们结婚生孩子一样,要先到祖宗那里,公安局那里,左邻右舍那里,告诉他 ...
- 为什么我们不要 .NET 程序员
英文原文:Why we don’t hire .NET programmers,编译:外刊IT评论 http://blog.jobbole.com/10389/ 也许你已经知道了,我们正在招聘最优秀的 ...
- Linux查看端口占用情况并释放端口占用
1.netstat -tunlp:查看所有tcp/udp端口占用及进程相关信息 2.netstat -tln | grep 端口号:查看特定端口占用情况 3.kill -9 进程ID(PID):释放指 ...
- Python关于Pyqt
参考百度文摘地址: https://jingyan.baidu.com/article/a3761b2ba2b8581576f9aa98.html 1 首先进行安装Pyqt5 pip3 install ...
- zabbix官网不能访问的问题
zabbix 3.4官方文档 https://www.zabbix.com/documentation/3.4/zh/start zabbix官网不能访问 一开始以为运营商限制就切换运营商发现 电信可 ...
- Schtasks命令详解(计划任务DOS批处理)
Schtasks 安排命令和程序定期运行或在指定时间内运行.从计划表中添加和删除任务,按需要启动和停止任务,显示和更改计划任务. 创建新的计划任务. 语法 schtasks/create/tnTask ...
- 记录 Ext 日历月份选择控件bug解决过程结果
目录 背景 代码 背景 项目使用 Ext.NET 2.2.0.40838 , 对应 Ext JS4.2 版本. 结果 2017/3/31 号的时候偶然间点日历选择控件选择2月,10月等月份突然就跳到3 ...