解析java中volatile关键字_java

在java多线程编程中经常volatile,有时候这个关键字和synchronized 或者lock经常有人混淆,具体解析如下:
在多线程的环境中会存在成员变量可见性问题: java的每个线程都存在一个线程栈的内存空间,该内存空间保存了该线程运行时的变量信息,当线程访问某一个变量值的时候首先会根据这个变量的地址找到对象的堆内存或者是栈堆存(原生数据类型)中的具体的内容,然后把这个内同赋值一个副本保存在本线程的线程栈中,紧接着对这个变量的一切操作在线程完成退出之前都和堆栈内存中的变量内容是没有关系的,操作的是自己线程栈中的副本。当操作完后会把操作完的结果写回到主内存中。假如有两个线程A和B,同事操作某一个变量x;A对x进行了加1操作,那么B获取的副本可能是x加1后的结果,也可能是x;为了保证获取内存中最新的数据变量 需要加上 volatile 关键字,这样在每次对x进行操作的时候都会去检查下线程栈中的变量的值是不是和住内存中变量的值一样,如果不一样会重新load。
eg:

public class ThreadSee {
//t1线程会根据flag的值做对应的操作,主线程会更改t1的值
 public static void main(String[] args) throws InterruptedException {
    ThReadTest th= new ThReadTest();
    Thread t1 = new Thread(th);
    t1.start();
    Thread.sleep(1000);
    th.changeFlag();
    Thread.sleep(2000);
    System.out.println(th.getFlag());
  } 

} 

class ThReadTest implements Runnable{ 

  //线程访问变量时会把其load到对应的线程栈中,每次操作时都要获取内存中最新的数据
  private volatile boolean stopflag;
  @Override
  public void run() {
    int i=0;
    while(!stopflag){
      i++;
      System.out.println("=="+Thread.currentThread().getName());
    }
    System.out.println("Thread finish:"+i);
  }
  public void changeFlag(){
    this.stopflag=true;
    System.out.println(Thread.currentThread().getName()+"***********");
  } 

  public boolean getFlag(){
    return stopflag;
  }
} 

上述代码如果去掉volatile,会一直死循环执行下去。
但是volatile不能保证线程安全的同步
eg:

public class ThreadSave implements Runnable{
  static ThreadSave sync = new ThreadSave();
  static volatile int j=0;
  //Lock lock =new ReentrantLock();
  public void inscane(){
    // lock.lock();
    for(int i=0;i<10000000;i++){
      j++;
    }
   //  lock.unlock();
  }
  @Override
  public void run() {
    inscane();
  }
  public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(sync);
    Thread t2 = new Thread(sync);
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(j);
  }
} 

根据上述代码执行的结果不是预期20000000,
因为对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的。
例如假如线程1,线程2 在进行线程栈与主内存read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值
在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6;
线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6;
导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。
综上所述:
volatile只会保证线程去做一个检查当前线程栈的变量值和主内存中数据值是否一样的这么一个动作,只此而已。而lock或者是synchronized 会保证某一时刻只有单个线程进入该方法,从而确保其线程安全性。
所以在如果多个线程去修改一个volatile变量那么没有实际的逻辑意义。如果一个线程去修改其他的线程依赖修改的变量值,此时是有作用的。

以上就是本文的全部内容,希望对大家的学习有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, 关键字
volatile
java volatile关键字、java中volatile关键字、java关键字解析、volatile关键字、volatile关键字的作用,以便于您获取更多的相关知识。

时间: 2024-12-22 21:01:22

解析java中volatile关键字_java的相关文章

深入解析Java中volatile关键字的作用_java

在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制. synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用synchronized 修饰的方法 或者 代码块.

谈谈Java中Volatile关键字的理解_java

volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机.volatile关键字虽然从字面上理解起来比较简单,但是要用好不是一件容易的事情. 一.前言 JMM提供了volatile变量定义.final.synchronized块来保证可见性. 用volatile修饰的变量,线程在每次使用变量的时候,都会读取变量修改后的最的值.volatile很容

Java中volatile关键字的作用与用法详解_java

volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以重获生机. volatile 关键字作用是,使系统中所有线程对该关键字修饰的变量共享可见,可以禁止线程的工作内存对volatile修饰的变量进行缓存. volatile 2个使用场景: 1.可见性:Java提供了volatile关键字来保证可见性. 当一个共享变量被volatile修饰时,它会保证修

详解Java中native关键字_java

 一. 什么是Native Method   简单地讲,一个Native Method就是一个java调用非java代码的接口.一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C.这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern "C"告知C++编译器去调用一个C的函数.    "A native method is a Java method whose implementatio

Java中Finally关键字_java

final:禁止多态开关~ 修饰变量:变量不能被改变 修饰类:类不能被继承 修饰方法:方法不能被重写 finally:用在异常处理的最后一个语句块 无论是否产生异常都要被执行~~~ Java代码 public final class FinallyTest { public static void main(String[] args) { try { throw new NullPointerException(); } catch (NullPointerException e) { Sys

彻底理解Java中this 关键字_java

this关键字再java里面是一个我认为非常不好理解的概念,:)也许是太笨的原因 this 关键字的含义:可为以调用了其方法的那个对象生成相应的句柄. 怎么理解这段话呢? thinking in java里面有这么一个例子 有两个同一个类型的对象,分别叫做a和b,那我们怎样区别在调用方法f()的时候,是谁再调用这个方法呢? 例如: class Banana { void f(int i){ /***方法主体*****/ } } Banana a = new Banana();//生成Banana

深度解析Java中volatile的内存语义实现以及运用场景_java

volatile内存语义的实现 下面,让我们来看看JMM如何实现volatile写/读的内存语义. 前文我们提到过重排序分为编译器重排序和处理器重排序.为了实现volatile内存语义,JMM会分别限制这两种类型的重排序类型.下面是JMM针对编译器制定的volatile重排序规则表: 举例来说,第三行最后一个单元格的意思是:在程序顺序中,当第一个操作为普通变量的读或写时,如果第二个操作为volatile写,则编译器不能重排序这两个操作. 从上表我们可以看出: 当第二个操作是volatile写时,

java中 volatile关键字具体什么作用

问题描述 我已经GOOGLE了很多文章 没有实质性的东西谁能写个小例子 能看出加 与 不加 volatile关键字的区别.直接能看到结果的就行 感激不尽 解决方案 例子之一:http://ifeve.com/concurrency-visibility/Java并发相关的东西直接上http://ifeve.com/解决方案二:简单说下现实中的使用,对于多线程争用的多读少改的变量就可以使用volatile.例如一个volatile boolean flag是用于对多个线程while(flag)循环

java中volatile关键字的含义

在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 同步块 和 volatile 关键字机制. synchronized 同步块大家都比较熟悉,通过 synchronized 关键字来实现,所有加上synchronized 和 块语句,在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法 或者 代码块.