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关键字的更多相关文章

  1. java线程学习之volatile关键字

    volatile变量的主要作用:是使变量在多个线程间可见. 在java中每一个线程都会有一块工作内存区,其中存放着所有线程共享的主内存的变量值的拷贝.当线程执行时,它在自己的工作内存区操作这些变量,为 ...

  2. java 线程Thread 技术--线程状态与同步问题

    线程技术第三篇: 线程的状态: 1. 创建状态: 当用new 操作符创建一个新的线程对象时,该线程就处于创建状态,系统不为它分配资源 2.可运行状态:当线程调用start 方法将为线程分配必须的系统资 ...

  3. java 线程Thread 技术--1.5 Executor Executors,ThreadPool,Queue

    Executors : Executors ,就是一个线程工具类:大部分操作线程的方法,都可以在这个工具类中就行创建,执行,调用一些线程的方法: Executor : 用于执行和提交一个runnabl ...

  4. java 线程Thread 技术--1.5 Future与Callable

    Callable: 从官方文档说起: 通过实现callable 的called 方法可以使一个任务可以返回一个结果以及可能抛出一个异常: callable 与runnable 是相似的,可以被其他线程 ...

  5. java 线程Thread 技术--1.5Lock 与condition 演示生产者与消费模式

    在jdk 1.5 后,Java 引入了lock 锁来替代synchronized ,在使用中,lock锁的使用更加灵活,提供了灵活的 api ,不像传统的synchronized ,一旦进入synch ...

  6. java 线程Thread 技术--方法演示生产与消费模式

    利用wait 与notifyAll 方法进行演示生产与消费的模式的演示,我们两个线程负责生产,两个线程消费,只有生产了才能消费: 在effective Java 中有说过: 1. 在Java 中 ,使 ...

  7. java 线程Thread 技术--线程创建源码解释

    永远不要忘记最基础的东西,只有把最基础的知识打牢靠,才能够使你走的更远,我将从今天开始,进行线程知识的回顾,一些常用知识点,以及java1.5 引入的并发库,进行详细的讲解与总结 创建线程的目的是为了 ...

  8. java 线程Thread 技术--线程方法详解

    Thread 类常用的方法与Object类提供的线程操作方法:(一个对象只有一把锁

  9. java 线程Thread 技术--创建线程的方式

    在第一节中,对线程的创建我们通过看文档,得知线程的创建有两种方式进行实现,我们进行第一种方式的创建,通过继承Thread 类 ,并且重写它的run 方法,就可以进行线程的创建,所有的程序执行都放在了r ...

随机推荐

  1. 给大厨写的R数据分析代码

    ###************************************** 新老客户统计 ***************************************### dachu &l ...

  2. Python3根据基础概率随机生成选项

    想要实现一个功能:不同事件发生的基础概率不同,根据基础概率来随机生成选项. 比如,北京的秋天有四种状态,并分别对应一个基础概率,然后随机生成某一天的天气情况. weatherlist = ['Sunn ...

  3. linux下一些重要命令的了解

    linux下一些比较重要的命令: du命令: 查看使用空间: 格式: du [选项][文件] 参数: -a  显示目录中个别文件的大小. -b  显示目录或文件大小时,以byte为单位. -c  除了 ...

  4. 算法分析(2)——大O和大Θ

    当一个软件遇到了性能瓶颈时,首要的改进是软件功能重构,适当删除可能拖垮系统的业务需求.客户对“实时”相当感兴趣,然而又有几个使用者能够真正清楚什么地方应该是实时的?这一点同样体现在其它行业,生厂商想要 ...

  5. Ubuntu 下解压tar.xz方法

    参考地址:https://www.cnblogs.com/baby123/p/6611169.html

  6. OSS阿里云上传文件 前端js下载url跨域问题

    场景: 1.后端上传文件至阿里云OSS,返回得到一个URL. 2.前端用这个URL下载文件,ajax请求异常:No 'Access-Control-Allow-Origin' header is pr ...

  7. [zz]LyX 入门教程

    http://blog.sina.com.cn/s/blog_630e5dec0100w3jl.html The LyX Tutorial by the LyX Team 1 目录 Chapter 1 ...

  8. Scrapy实战篇(一)之爬取链家网成交房源数据(上)

    今天,我们就以链家网南京地区为例,来学习爬取链家网的成交房源数据. 这里推荐使用火狐浏览器,并且安装firebug和firepath两款插件,你会发现,这两款插件会给我们后续的数据提取带来很大的方便. ...

  9. MySQL SQL审核平台 inception+archer2.0(亲测)

    docker run -d --privileged -v `pwd`/archer_data:/data -p 9306:3306 --name archer --hostname archer - ...

  10. 什么是Java序列化,如何实现java序列化

      简要解释: 序列化就是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化.可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间. 序列化是为了解决在对对象流进行读写操作时所 ...