volatile是确保内存之间元素可见的关键字,效率比synchornized高,但是并不保证线程的原子性
这里一共有main线程和new出来的两个线程,两个线程中各自有自己的缓存,
如果没有volatile的话,每次都一般只会从自己的线程的缓冲区里面拿值,所有main改变了也没什么用,而加了volatile的值一旦发生改变,存有running值的线程会自动被提示
该值已过期,就会再从主线程里面重新获取running,
public class testVolatile {
//可见性 跟JMM有关
volatile boolean running=true;
void m(){
System.out.println(" m start");
while(running){
}
System.out.println("e end!");
}
public static void main(String[] args) {
testVolatile t=new testVolatile();
new Thread(t::m,"t1").start();
try{
TimeUnit.SECONDS.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
t.running=true;
}
}
不过volatile 并不能保证多个线程共同修改变量时所带来的不一致问题
一个线程从主线程的内存中读到0,加一,与此同时另一个线程也读到了0,因为有volatile,所以volatile所以主线程的count变为1,而另一个线程将1也放到主线程中,只会覆盖原有的1,所以执行了两个线程只加了1,
public class testVolatile {
volatile int count=0;
void m(){
for(int i=0;i<10000;i++) count++;
}
public static void main(String[] args) {
testVolatile t=new testVolatile();
List<Thread> threads=new ArrayList<>();
for(int i=0;i<10;i++){
threads.add(new Thread(t::m,"thread"+1));
}
threads.forEach((o)->o.start());
threads.forEach((o)->{
try{
o.join();
}catch (InterruptedException e){
e.printStackTrace();
}
});
System.out.println(t.count);
}
}
count++不具备原子性。可以用synchornized或者AtomicInteger解决
AtomicInteger count=new AtomicInteger(0);
// volatile int count=0;
void m(){
for(int i=0;i<10000;i++) count.incrementAndGet();
//count++;
}