一个线程对主内存的修改可以及时被其它线程观察到
对于可见性
Java
提供了synchonized
和volatile
通过加入内存屏障和禁止重排序优化来实现,保证可见性不保证原子性 对
volatile
变量进行写操作时,会在写操作后加入一条store
屏障指令,将工作内存变量值刷新到主内存。
对
volatile
变量进行读操作时,会在读操作前加入一条load
屏障指令,从主内存读取共享变量。
通过上面两点,任何时候,不同线程总能看到该变量的最新值.所有的操作都是
CPU
级别的。
volatile
就线程安全了package com.keytech.task;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class VolatileTest {
private static Integer clientTotal=5000;
private static Integer threadTotal=200;
private static volatile Integer count=0;
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
Semaphore semaphore=new Semaphore(threadTotal);
for (int i = 0; i < clientTotal; i++) {
executorService.execute(()->{
try{
semaphore.acquire();
update();
semaphore.release();
}catch (Exception e){
e.printStackTrace();
}
});
}
executorService.shutdown();
System.out.println("count:"+count);
}
private static void update(){
count++;
}
}
//count:4988
虽然使用了
volatile
,但是线程不安全。原因:update
是非原子性的。
private static void update() {
count++; //分3步
//1.取出当前count值
//2.count + 1
//3.count 重新写回主存
}
假设同时有两个线程进行操作,两个线程同时执行到第一步(从内存中读取最新值)得到一样的最新的结果,然后进入第二步(+1操作)并进行第三步(从新写回主存)。尽管第一步获取的值是一样的,但是同时将+1后的操作写回主存,这样就会丢掉某个+1的操作,这样就会出现线程不安全问题
volatile
进行多线程加是线程不安全的,不适合计数volatile
不具备原子性volatile
的使用场景volatile boolean flag = false;
//线程1
context = loadContext();
flag = true;
//线程2
while(!flag){
sleep();
}
todo(context);
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。