当前位置: 移动技术网 > IT编程>开发语言>Java > java volatile关键字使用方法及注意事项

java volatile关键字使用方法及注意事项

2019年07月19日  | 移动技术网IT编程  | 我要评论

java volatile关键字使用方法及注意事项

什么是volatile关键字

volatile 关键字在多线程程序中起着很重要的作用。当多个线程操作同一个变量时,每个线程将拥有对那个变量的本地缓存拷贝,因此,当某一个线程修改了这个变量的值时,实际上修改的是它本地缓存中的变量值,而不是主内存中的变量值,操作这个变量的其他线程并不知道这个变量的值被改变了。为了避免这种情况,我们可以用 valatile 关键字声明这个变量,用 valatile 声明了这个变量之后,变量将不在本地缓存中保存,而在主内存中保存,当有线程修改了它的值以后,它的更新值将被更新到主内存当中,随后,其他线程也能访问更新后的值。当一个变量被声明为 volatile 后,java 内存模型确保所有使用该变量的线程能看到相同的、一致的值。

volatile关键字使用

首先,创建 volatiledata 类,代码如下:

public class volatiledata {

  //声明为volatile类型
  private volatile int counter = 0;

  /**
  * 返回counter变量的值
  * @return
  */
  public int getcounter() {
    return counter;
  }

  /**
  * 自增counter变量的值
  */
  public void increasecounter() {
    ++counter;
  }
}

接下来创建 volatilethread 类,代码如下:

public class volatilethread extends thread {
  private final volatiledata volatiledata;

  public volatilethread(volatiledata volatiledata) {
    this.volatiledata = volatiledata;
  }

  /**
  * 调用volatiledata类中的两个方法,进行取值和自增操作
  */
  @override
  public void run() {
    int oldvalue = volatiledata.getcounter();
    system.out.println("[thread " + thread.currentthread().getid() + "]: old value = " + oldvalue);
    volatiledata.increasecounter();
    int newvalue = volatiledata.getcounter();
    system.out.println("[thread " + thread.currentthread().getid() + "]: new value = " + newvalue);
  }
 }

最后,创建 volatilemain 类,对以上程序进行测试,代码如下:

public class volatilemain {

  private final static int total_threads = 2;

  public static void main(string[] args) throws interruptedexception {
    volatiledata volatiledata = new volatiledata();

    thread[] threads = new thread[total_threads];
    for(int i = 0; i < total_threads; ++i)
      threads[i] = new volatilethread(volatiledata);

    //开始读取变量值的操作
    for(int i = 0; i < total_threads; ++i)
      threads[i].start();

    //等待所有线程操作终止
    for(int i = 0; i < total_threads; ++i)
      threads[i].join();
  }
}

在 volatilemain 类中,使用了两个线程来访问 volatile 变量,输出如下:

[thread 10]: old value = 0
[thread 11]: old value = 0
[thread 10]: new value = 1
[thread 11]: new value = 2

从输出可以看到,首先,两个线程都输出了相同的值,接着,在 increasecounter 方法被调用之后,两个线程都访问和输出了最新的 volatile 变量的值。

happens-before 关系

在使用 volatile 关键字时,不得不提一下 java 内存模型的 happens-before 关系。happens-before 关系是 java 内存模型的一个重要方面。它建立在两个不同的事件之间,使第一个事件对对象的所有改变都可以被第二个事件看到和反映出。比如当一个线程对 volatile 变量进行写操作后,另一个线程随后访问该变量,happens-before 关系就建立了。因此,所有对 volatile 变量的改变对其他线程来说是可见的。

需要注意的

当在程序中使用 volatile 关键字时,我们必须注意以下几点:

  1. volatile 关键字并不能消除原子之间的同步操作的需要,因为内存一致性错误仍然是可能的
  2. 使用原子变量比使用 synchronized 同步代码更有效率,但是为了避免内存一致性错误,需要作出额外的努力
  3. volatile 关键字不能替代 synchronized 同步代码块和方法

以上就是关于java volatile关键字的使用方法,如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网