Java中关于volatile关键字的使用和注意事项
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 关键字时,我们必须注意以下几点:
volatile 关键字并不能消除原子之间的同步操作的需要,因为内存一致性错误仍然是可能的
使用原子变量比使用 synchronized 同步代码更有效率,但是为了避免内存一致性错误,需要作出额外的努力
volatile 关键字不能替代 synchronized 同步代码块和方法
以上就是Java中关于volatile关键字的使用和注意事项的详细内容,更多请关注其它相关文章!
推荐阅读
-
Python2和Python3中urllib库中urlencode的使用注意事项
-
详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)
-
微信小程序授权 获取用户的openid和session_key【后端使用java语言编写】,我写的是get方式,目的是测试能否获取到微信服务器中的数据,后期我会写上post请求方式。
-
深色系背景在UI设计中的使用技巧和注意事项
-
小程序中this.setData的使用和注意事项
-
Oracle中 关于数据库存储过程和存储函数的使用
-
关于python中 and 和 or 的一些特殊使用
-
Angularjs使用ng-repeat中$even和$odd属性的注意事项
-
Java中异常上抛和异常捕捉的具体使用案例
-
Python中关于模块的使用和学习讲解