Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

volatile关键字

六式 2020-02-16 12:55:00 阅读数:17 评论数:0 点赞数:0 收藏数:0

volatile的作用

阅读本篇前参见上一篇博文https://www.cnblogs.com/dearnotes/p/12290564.html

1.保证此变量对所有线程的可见性

(当一条线程修改了这个变量的值,新值对于其他线程来说立即得知)
虽然是这样,但是我们并不能因此认为基于violate变量的运算在并发下是安全的。

public class VolatileTest extends Thread{
static volatile int increase = 0;
static AtomicInteger aInteger=new AtomicInteger();//对照组
static void increaseFun() {
increase++;
aInteger.incrementAndGet();
}
public void run(){
int i=0;
while (i < 10000) {
increaseFun();
i++;
}
}
public static void main(String[] args) {
VolatileTest vt = new VolatileTest();
int THREAD_NUM = 10;
Thread[] threads = new Thread[THREAD_NUM];
for (int i = 0; i < THREAD_NUM; i++) {
threads[i] = new Thread(vt, "线程" + i);
threads[i].start();
}
//idea中会返回主线程和守护线程,如果用Eclipse的话改为1
while (Thread.activeCount() > 2) {
Thread.yield();
}
System.out.println("volatile的值: "+increase);
System.out.println("AtomicInteger的值: "+aInteger);
}
}

这段代码如果能保证并发安全的话结果应该是100000,但是实际结果会小于这个数字。
为什么呢?
volatile修饰的变量不能保证它的原子性。
由于volate变量只能保证可见性,在不符合以下两条运算场景中,我们仍然要通过加锁(使用synchronized或java.util.concurrent中的原子类)来保证原子性。

  • 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值
  • 变量不需要与其他的状态变量共同参与不变约束

单独的violate适用场景参见https://blog.csdn.net/vking_wang/article/details/9982709

2.禁止指令重排序优化

参见https://www.cnblogs.com/dearnotes/p/12268971.html中的双检锁。

版权声明
本文为[六式]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/dearnotes/p/12269978.html