volatile 的是与非

本贴最后更新于 2641 天前,其中的信息可能已经时移世易

volatile 关键字所做的事情

被 volatile 修饰的属性,在修改属性的值的时候,会增加一个内存屏障,将包括该属性在内的前面所有修改的属性刷新 CPU 缓存,做到属性的变化对其他线程可见。

volatile 关键字的用处

保证属性的安全,即属性的任何变化都能够做到及时对其他线程可见.

volatile 不等同于线程安全

由于一个线程会将临界变量的值压入线程栈,类似在线程栈中对临界属性做了备份,所以即使临界属性时时保证为最新的值,但无法更改线程栈中的备份,所以也就无法做到线程安全。

下面来看一个具体示例,用来解释线程是如何备份变量的值。

java 源码:

public class T2 {


    private Integer i = 1;

    public void test3() {
        i = i + 2;
    }
}

反汇编:

Compiled from "T2.java"
public class test.T2 {
  public test.T2();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: aload_0
       5: iconst_1
       6: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
       9: putfield      #3                  // Field i:Ljava/lang/Integer;
      12: return

  public void test3();
    Code:
       0: aload_0
       1: aload_0
       2: getfield      #3                  // Field i:Ljava/lang/Integer; -- 将属性i的引用压入栈顶
       5: invokevirtual #4                  // Method java/lang/Integer.intValue:()I --i的引用出栈并调用intValue()方法,并将结果压入栈顶
       8: iconst_2
       9: iadd
      10: invokestatic  #2                  // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
      13: putfield      #3                  // Field i:Ljava/lang/Integer;
      16: return
}

可以看出,在 test3 方法中, 虚拟机会拿到临界变量 i 的值,并且将 i 的值压入栈顶,后续计算操作使用的是线程栈中的值进行操作。

结论

所以,volatile 可以保证属性安全,但并非保证线程安全。

说明

博主是个水货,如果写的不对的地方欢迎大家指出来。
原文地址

  • volatile
    7 引用 • 9 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3167 引用 • 8207 回帖 • 2 关注
  • Concurrent
    4 引用 • 2 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • F0CUS

    看看能不能回复

  • 其他回帖
  • 哎,不懂。继续科普

    Volatile 变量

    Volatile 变量具有 synchronized 的可见性特性,但是不具备原子特性。这就是说线程能够自动发现 volatile 变量的最新值。Volatile 变量可用于提供线程安全,但是只能应用于非常有限的一组用例:多个变量之间或者某个变量的当前值与修改后值之间没有约束。因此,单独使用 volatile 还不足以实现计数器、互斥锁或任何具有与多个变量相关的不变式(Invariants)的类(例如 “start <=end”)。

    出于简易性或可伸缩性的考虑,您可能倾向于使用 volatile 变量而不是锁。当使用 volatile 变量而非锁时,某些习惯用法(idiom)更加易于编码和阅读。此外,volatile 变量不会像锁那样造成线程阻塞,因此也很少造成可伸缩性问题。在某些情况下,如果读操作远远大于写操作,volatile 变量还可以提供优于锁的性能优势。