1.保证可见性
不加volatile程序就会死循环
加volatile就可以保证可见性
package com.liao.jvolatile;
import java.util.concurrent.TimeUnit;
public class JMMDemo {
private volatile static int num = 0;
//不加volatile程序就会死循环
//加volatile就可以保证可见性
public static void main(String[] args) {
new Thread(()->{
while (num==0){ //线程1对主内存的变化是不知道的
}
}).start();
try {
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
num = 1;
System.out.println(num);
}
}
2.不保证原子性
原子性:不可分割的
线程A在执行任务的时候,不能被打扰的,也不能被分割。要么同时成功,要么同时失败
package com.liao.jvolatile;
//synchronized一定保证原子性
public class VolatileDemo {
private volatile static int num = 0;
public static void add(){
num++;
}
public static void main(String[] args) {
//理论上num结果应该为2万
for (int i = 1; i <= 20; i++) {
new Thread(()->{
for (int j = 1; j <= 1000; j++) {
add();
}
}).start();
}
while (Thread.activeCount()>2){ //activeCount还存活的线程的数量,默认执行的main,gc线程
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+" ----"+num);
}
}
如果不加lock和synchronized,怎么保证原子性?
使用原子类解决原子性问题**:**
package com.liao.jvolatile;
import java.util.concurrent.atomic.AtomicInteger;
//synchronized一定保证原子性
public class VolatileDemo {
private volatile static AtomicInteger num = new AtomicInteger();
public static void add(){
num.getAndIncrement(); //getAndIncrement是AtomicInteger的+1方法 运用了底层的CAS
}
public static void main(String[] args) {
//理论上num结果应该为2万
for (int i = 1; i <= 20; i++) {
new Thread(()->{
for (int j = 1; j <= 1000; j++) {
add();
}
}).start();
}
while (Thread.activeCount()>2){ //activeCount还存活的线程的数量,默认执行的main,gc线程
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+" ----"+num);
}
}
这些类的底层都是直接和操作系统挂钩,在内存中修改值!Unsafe类是一个很特殊的存在