以下代码验证volatile的可见性可不保证原子性
可见性代码解释
当自己创建的线程还没有修改num值时,一直在while里面循环,当5秒休眠完成后修改成功,因为可见性,主线程知道已经num修改完毕跳出while循环
不保证原子性代码解释
如果是保证原子性的那么num将会变成20000,实际上会num会比20000少,因为n++的时候被其他的线程打断了,若要保证原子性可以使用AtomicInteger代替。详情请看代码表示
禁止指令重排
指令重排就是java编译的时候如果没有依赖关系的时候,可能会让java的代码编译不按代码所写的顺序去编译,volatile禁止指令重排就是类似于会让各个代码直接增加一个屏障,保证了一种顺序性。
class Number{
volatile int num = 0;
public void numTo60(){
this.num = 60;
}
public void numIncrement(){
num++;
}
AtomicInteger atomicInteger = new AtomicInteger();
public void addAtomic(){
this.atomicInteger.getAndIncrement();
}
}
public class VolatileTest {
public static void main(String[] args) {
volatileEnableSee();//可见性验证
//volatileNotAtomic();//Volatile不保证原子性验证
// atomicInteger();//AtomicInteger保证原子性
}
static void volatileEnableSee(){
Number number = new Number();
new Thread(()->{
try {
TimeUnit.SECONDS.sleep(5);
number.numTo60();
}catch (Exception e){
e.printStackTrace();
}
},String.valueOf("A")).start();
while (number.num == 0){
}
System.out.println(Thread.currentThread().getName()+"\t num to " + number.num);
}
static void volatileNotAtomic(){
Number number = new Number();
for (int i = 0; i <20 ; i++) {
new Thread(()->{
for (int j = 0; j <1000 ; j++) {
number.numIncrement();
}
},String.valueOf(i)).start();
}
if (Thread.activeCount()>2){
Thread.yield();
}
System.out.println(number.num);
}
static void atomicInteger(){
Number number = new Number();
for (int i = 0; i <20 ; i++) {
new Thread(()->{
for (int j = 0; j <1000 ; j++) {
number.addAtomic();
}
},String.valueOf(i)).start();
}
while (Thread.activeCount()>2){
Thread.yield();
}
System.out.println(Thread.currentThread().getName()+"\t atomic is:"+ number.atomicInteger );
}