volatile详解
接下来,我们详细讲述一下volatile关键字
volatile关键字具有两重语义

  • 保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这个新值对其他线程来说是立即可见的。
  • 禁止指令重排序

依然使用上文RunThread案例说明,上文中已经提到了,由于主线程修改了isRunning的值后,RunThread线程并没有看到其值的变化,因此,进入了死循环,但是当isRunning加上volatile关键字后,效果就不一样了。

  1. 使用volatile关键字会强制将修改的值立即写入主存;
  2. 使用volatile关键字的话,当主线程修改时,会导致RunThread的工作内存中isRunning变量的缓存值变得无效。
  3. 由于RunThread的工作内存中缓存变量isRunning缓存无效,所以会再次从主存中读取isRunning变量值。

这样就保证了RunThread可以顺利结束。

关于原子性,我们先看个例子:

public class TestCount
{
private volatile int n; public void increase()
{
n ++;
} public static void main(String[] args)
{
TestCount count = new TestCount();
for(int i=0; i<10; i++)
{
new Thread(){
public void run() {
for(int j=0;j<1000;j++)
count.increase();
};
}.start();
} if(Thread.activeCount() > 1)
{
Thread.yield();
}
System.out.println(count.n);
}
}

关于这个结果,应该很多人会认为是10000吧。但是实际上,运行结果小于10000,这是由于n++操作并非原子性操作,其涉及三个操作

  1. 读出n的旧知
  2. 对n+1
  3. 写入新值

虽然volatile可以保证每个线程读取到的是最新的内存值,但是,如果10个线程第一步都是正确的,第二步和第三步单线程看的话也都是没有问题的,但是如果并发的话,就会导致同一个值被多次写入了内存。
可见volatile并不能保证原子性操作。
对于这一类问题,我们可以通过synchronized、lock或者原子操作类经行操作。
synchronized版本:

public class TestCount
{
public int inc = 0; public synchronized void increase() {
inc++;
} public static void main(String[] args) {
final TestCount test = new TestCount();
for(int i=0;i<10;i++){
new Thread(){
public void run() {
for(int j=0;j<1000;j++)
test.increase();
};
}.start();
} while(Thread.activeCount()>1) //保证前面的线程都执行完
Thread.yield();
System.out.println(test.inc);
}
}

lock版本:

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; public class TestCount
{
public int inc = 0;
Lock lock = new ReentrantLock(); public void increase() {
lock.lock();
try {
inc++;
} finally{
lock.unlock();
}
} public static void main(String[] args) {
final TestCount test = new TestCount();
for(int i=0;i<10;i++){
new Thread(){
public void run() {
for(int j=0;j<1000;j++)
test.increase();
};
}.start();
} while(Thread.activeCount()>1) //保证前面的线程都执行完
Thread.yield();
System.out.println(test.inc);
}
}

原子操作类版本:

import java.util.concurrent.atomic.AtomicInteger;

public class TestCount
{
public AtomicInteger inc = new AtomicInteger(); public void increase() {
inc.getAndIncrement();
} public static void main(String[] args) {
final TestCount test = new TestCount();
for(int i=0;i<10;i++){
new Thread(){
public void run() {
for(int j=0;j<1000;j++)
test.increase();
};
}.start();
} while(Thread.activeCount()>1) //保证前面的线程都执行完
Thread.yield();
System.out.println(test.inc);
}
}

对于有序性,我们可以看下下面的这个例子:

//线程1:
context = loadContext(); //语句1
inited = true; //语句2 //线程2:
while(!inited ){
sleep()
}
doSomethingwithconfig(context);

如果没有对inited加volatile关键字,则可能会对语句1和语句2进行调整,因此两者并无依赖关系,并且单线程下,也并不会影响结果。但是两个线程下,可能由于context并没有初始化完成,导致意想不到的结果。
如果对inited加上volatile,这个问题就不会发生了。语句1和语句2的执行顺序则不会被调整。

volatile关键字解析(二)的更多相关文章

  1. Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  2. (转)Java并发编程:volatile关键字解析

    转:http://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或 ...

  3. volatile关键字解析(转)

    volatile关键字解析 转载:http://www.cnblogs.com/dolphin0520/p/3920373.html volatile这个关键字可能很多朋友都听说过,或许也都用过.在J ...

  4. Java并发编程:volatile关键字解析(转载)

    转自https://www.cnblogs.com/dolphin0520/p/3920373.html Java并发编程:volatile关键字解析   Java并发编程:volatile关键字解析 ...

  5. Java并发编程学习:volatile关键字解析

    转载:https://www.cnblogs.com/dolphin0520/p/3920373.html 写的非常棒,好东西要分享一下 Java并发编程:volatile关键字解析 volatile ...

  6. Java并发编程:volatile关键字解析-转

    Java并发编程:volatile关键字解析 转自海子:https://www.cnblogs.com/dayanjing/p/9954562.html volatile这个关键字可能很多朋友都听说过 ...

  7. Java并发编程之三:volatile关键字解析 转载

    目录: <Java并发编程之三:volatile关键字解析 转载> <Synchronized之一:基本使用>   volatile这个关键字可能很多朋友都听说过,或许也都用过 ...

  8. Java 并发:volatile 关键字解析

    摘要: 在 Java 并发编程中,要想使并发程序能够正确地执行,必须要保证三条原则,即:原子性.可见性和有序性.只要有一条原则没有被保证,就有可能会导致程序运行不正确.volatile关键字 被用来保 ...

  9. 6、Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在 ...

  10. 转:Java并发编程:volatile关键字解析

    Java并发编程:volatile关键字解析 Java并发编程:volatile关键字解析 volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字, ...

随机推荐

  1. C++中去掉string字符串中的\r\n等

    string imagedata;imagedata = “dudau\r\ndadafca\r\n” CString Image; Image = imagedata.c_str(); Image. ...

  2. c++ 中 BOOL与bool TRUE与true FALSE与false 区别

    转自:http://blog.chinaunix.net/uid-28458801-id-3941112.html   FALSE/TRUE与false/true的区别 1.FALSE/TRUE与fa ...

  3. c++类static成员

    转自:http://blog.csdn.net/heyabo/article/details/8681516 参考文献:1.http://www.yesky.com/20010828/194000.s ...

  4. CSS Fonts(字体)

    CSS Fonts(字体) 一.serif和sans-serif字体之间的区别 注意: 在计算机屏幕上,sans-serif字体被认为是比serif字体容易阅读. 二.CSS字型 在CSS中,有两种类 ...

  5. oracle错误一览表

    ORA-00001: 违反唯一约束条件 (.)ORA-00017: 请求会话以设置跟踪事件ORA-00018: 超出最大会话数ORA-00019: 超出最大会话许可数ORA-00020: 超出最大进程 ...

  6. Base64转Blob

    最近碰见一个问题,a链接的href为base64,但在chrome下载时显示下载失败,经查询,base64过大会在某些浏览器上下载失败(如新版chrome),解决方法是将base64转为blob fu ...

  7. C++第二次上机5-5

    建立一个复数类Complex,实数和虚数是其私有数据成员: 建立复数类的无参和参数化构造函数: 建立一个 *(乘号)的运算符重载,以便于对两个复数直接进行乘法运算: 建立输出函数void displa ...

  8. ISSCC 2017论文导读 Session 14 Deep Learning Processors,A 2.9TOPS/W Deep Convolutional Neural Network SOC

    最近ISSCC2017大会刚刚举行,看了关于Deep Learning处理器的Session 14,有一些不错的东西,在这里记录一下. A 2.9TOPS/W Deep Convolutional N ...

  9. Centos7.2 FastDFS_V5.05 集群的安装与配置1

    环境: Centos 7.2/64位  两台服务器 都为tracker 和 storage 10.100.0.1  storage tracker10.100.0.2  storage tracker ...

  10. 使用iview--1

    在任意一个你想创建项目的路径下 每次输入就输一致的就可以 /*************************安装选项开始****************/ 回车再次回车就如下,输入Y 继续 回车,输 ...