`
demojava
  • 浏览: 548832 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

【转】java中volatile关键字的含义

    博客分类:
  • JAVA
 
阅读更多

用在多线程,同步变量。 线程为了提高效率,将某成员变量(如A)拷贝了一份(如B),线程中对A的访问其实访问的是B。只在某些动作时才进行A和B的同步。因此存在A和B不一致的情况。volatile就是用来避免这种情况的。volatile告诉jvm, 它所修饰的变量不保留拷贝,直接访问主内存中的(也就是上面说的A)

版权声明 :转载时请以超链接形式标明文章原始出处和作者信息及本声明
http://aleung.blogbus.com/logs/32090434.html

在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器)。为了性能,一个线程会在自己的memory中保持要访问的变量的副本。这样就会出现同一个变量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memory中的值不一致的情况。

一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程memory中。以下例子展现了volatile的作用:

public class StoppableTask extends Thread {

  private volatile boolean pleaseStop;


  public void run() {

    while (!pleaseStop) {

     // do some stuff...

    }

 }


  public void tellMeToStop() {

   pleaseStop = true;

  }

}

 假如pleaseStop没有被声明为volatile,线程执行run的时候检查的是自己的副本,就不能及时得知其他线程已经调用tellMeToStop()修改了pleaseStop的值。

Volatile一般情况下不能代替sychronized,因为volatile不能保证操作的原子性,即使只是i++,实际上也是由多个原子操作组成:read i; inc; write i,假如多个线程同时执行i++,volatile只能保证他们操作的i是同一块内存,但依然可能出现写入脏数据的情况。如果配合Java 5增加的atomic wrapper classes,对它们的increase之类的操作就不需要sychronized。

Reference:
http://www.javamex.com/tutorials/synchronization_volatile.shtml
http://www.javamex.com/tutorials/synchronization_volatile_java_5.shtml
http://www.ibm.com/developerworks/cn/java/j-jtp06197.html

 

恐怕比较一下volatile和synchronized的不同是最容易解释清楚的。volatile是变量修饰符,而synchronized则作用于一段代码或方法;看如下三句get代码:

int i1;             
int geti1() {return i1;} 
volatile int i2; 
int geti2()
{
 return i2;
} 
int i3;              
synchronized int geti3() {
 return i3;
} 
geti1()

 得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。
  而 geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经 volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。
  既然volatile关键字已经实现了线程间数据同步,又要 synchronized干什么呢?呵呵,它们之间有两点不同。首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“ 主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步:
1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放)
2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])
3. 代码块被执行
4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值)
5. 线程释放监视this对象的对象锁
  因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。

 

volatile关键字相信了解Java多线程的读者都很清楚它的作用。volatile关键字用于声明简单类型变量,如int、float、 boolean等数据类型。如果这些简单数据类型声明为volatile,对它们的操作就会变成原子级别的。但这有一定的限制。例如,下面的例子中的n就不是原子级别的:

 

package  mythread;

public   class  JoinThread  extends  Thread
{
     public   static volatile int  n  =   0 ;
    public   void  run()
    {
         for  ( int  i  =   0 ; i  <   10 ; i ++ )
             try 
        {
                n  =  n  +   1 ;
                sleep( 3 );  //  为了使运行结果更随机,延迟3毫秒 

            }
             catch  (Exception e)
            {
            }
    }

     public   static   void  main(String[] args)  throws  Exception
    {

        Thread threads[]  =   new  Thread[ 100 ];
         for  ( int  i  =   0 ; i  <  threads.length; i ++ )
             //  建立100个线程 
            threads[i]  =   new  JoinThread();
         for  ( int  i  =   0 ; i  <  threads.length; i ++ )
             //  运行刚才建立的100个线程 
            threads[i].start();
         for  ( int  i  =   0 ; i  <  threads.length; i ++ )
             //  100个线程都执行完后继续 
            threads[i].join();
        System.out.println( " n= "   +  JoinThread.n);
    }
} 

  上面的代码将n=n+1改成了inc(),其中inc方法使用了synchronized关键字进行方法同步。因此,在使用volatile关键字时要慎重,并不是只要简单类型变量使用volatile修饰,对这个变量的所有操作都是原来操作,当变量的值由自身的上一个决定时,如n=n+1、n++ 等,volatile关键字将失效,只有当变量的值和自身上一个值无关时对该变量的操作才是原子级别的,如n = m + 1,这个就是原级别的。所以在使用volatile关键时一定要谨慎,如果自己没有把握,可以使用synchronized来代替volatile。

 

转载连接:

http://sakyone.iteye.com/blog/668091

 

分享到:
评论

相关推荐

    java volatile 关键字实战

    java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java volatile 关键字实战java ...

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

    ### Java并发编程:volatile关键字解析 #### 一、内存模型的相关概念 在深入了解`volatile`关键字之前,我们首先需要理解计算机内存模型的一些基本概念。在现代计算机系统中,CPU为了提高执行效率,会将频繁访问的...

    深入解析Java中的volatile关键字:原理、应用与实践

    在Java并发编程中,volatile关键字是一种轻量级的同步机制,它用于确保变量的可见性和有序性。本文将详细探讨volatile关键字的工作原理、使用场景以及如何在实际开发中正确使用volatile。 volatile关键字是Java并发...

    Java并发volatile关键字.docx

    Java并发编程中,volatile关键字扮演着重要的角色,它是一种轻量级的同步机制,与synchronized相比,volatile在性能上更优,因为它不会导致线程阻塞。在深入理解volatile的关键特性之前,我们需要先了解Java内存模型...

    java里的volatile关键字详解

    "Java中的Volatile关键字详解" Java中的Volatile关键字详解是Java中的一种关键字,用于保证线程之间的可见性、原子性和有序性。下面是对Java中的Volatile关键字详解的知识点总结: 一、基本概念 1. 可见性:可见...

    Java中volatile关键字的总结.docx

    Java中的`volatile`关键字是用于处理并发编程中线程间通信和可见性的重要工具。它是一种轻量级的同步机制,比`synchronized`锁更为高效,因为它不会导致线程上下文的切换和调度,减少了不必要的开销。然而,`...

    Java中volatile关键字实现原理

    Java中volatile关键字实现原理 volatile关键字是Java语言中的一种机制,用于保证变量在多线程之间的可见性。它是Java.util.concurrent包的核心,没有volatile就没有那么多的并发类供我们使用。本文详细解读一下...

    java volatile 关键字 学习

    java volatile 关键字 学习

    Java线程:volatile关键字

    Java 线程 volatile 关键字详解 Java™ 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量。volatile 变量的同步性较差,但它有时更简单并且开销更低。volatile 变量可以被看作是一种 “程度较轻的 ...

    Java中volatile关键字的含义

    在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候可以万事大吉。  Java语言是支持多线程的,为了解决线程并发的问题,在语言内部引入了 ...

    一文精通Java中的volatile关键字

    Java中的`volatile`关键字是多线程编程中的一个重要概念,它的主要作用是确保共享变量的可见性和禁止指令重排序。本文将深入探讨`volatile`的关键特性、工作原理以及使用注意事项。 1. 可见性: `volatile`关键字...

    深入了解Java中Volatile关键字

    深入了解Java中Volatile关键字 Volatile关键字是Java语言中的一种关键字,主要用于解决多线程编程中的可见性、原子性和有序性问题。本文将详细介绍Volatile关键字的相关知识,并通过代码帮助大家更好地理解和学习。...

    Java中Volatile关键字详解及代码示例

    Java中Volatile关键字详解及代码示例 一、基本概念 在Java中,Volatile关键字是一个非常重要的概念,它与Java内存模型中的可见性、原子性和有序性息息相关。可见性是指线程之间的可见性,一个线程修改的状态对另一...

    java语言的volatile教程,java语言的volatile关键字是干什么用的

    java语言的volatile教程,java语言的volatile关键字到底怎么用

    解析java中volatile关键字

    Java中的`volatile`关键字是多线程编程中的一个重要概念,它的主要作用是解决并发环境下的可见性和有序性问题。在Java内存模型(JMM)中,每个线程都有自己的工作内存,其中包含了线程对共享变量的副本。线程间的...

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

    Java中的`volatile`关键字是一个非常重要的并发编程工具,它的作用主要体现在两个方面:**可见性**和**有序性**。本文将深入解析`volatile`的关键字特性及其在实际编程中的应用。 1. 可见性: 当一个共享变量被`...

    java里的volatile关键字详解.pdf

    java里的volatile关键字详解.pdf

    C++中volatile关键字及常见的误解总结

    在C++中,volatile关键字的定义与Java中的volatile关键字不同。C++中的volatile关键字主要用于提供对特殊地址的稳定访问,而不是用于线程同步。 在编译器对代码的优化中,编译器可能会对代码进行修改,以提高代码的...

    多方面解读Java中的volatile关键字.rar

    在Java编程语言中,`volatile`关键字是一个非常关键的同步原语,用于处理并发编程中的可见性和有序性问题。这个关键字对于理解Java内存模型(JMM)以及如何编写线程安全的代码至关重要。下面我们将从多个角度深入...

    Java——volatile关键字详解

    Java中的`volatile`关键字是一个非常重要的并发控制工具,它提供了比`synchronized`关键字更为轻量级的同步机制。`volatile`关键字的主要作用是确保多线程环境下的可见性和禁止指令重排序,但不保证原子性。 **...

Global site tag (gtag.js) - Google Analytics