JUC并发编程-Volatile

Volatile

Volatile 是 java 虚拟机提供轻量级的同步机制

有三点:

1、保证可见性;

2、不保证原子性;

3、禁止指令重排

1、保证可见性

package com.zkw.JUC并发编程.tvolatile;

import java.util.concurrent.TimeUnit;

public class JMMDemon {
    
    
    // 不加 volatile 线程对主内存的变化不知道,程序会变成死循环
    // 加 volatile 可以保证可见性
    private volatile static int num = 0;
    public static void main(String[] args) {
    
    
            new Thread(()->{
    
    
                while (num==0){
    
    

                }
            }).start();
        try {
    
    
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
    
    
            e.printStackTrace();
        }
       num = 1;
       System.out.println(num);
    }
}

2、不保证原子性

原子性:不可分割

线程A执行任务的时候,不能被打扰,也不可别分割,要么同时成功,要么同时失败

package com.zkw.JUC并发编程.tvolatile;

//不保证原子性
public class VDemon2 {
    
    
    private volatile static int num = 0;
    public  static void add(){
    
    
        num++;
    }

    public static void main(String[] args) {
    
    
        for (int i = 1; i <= 20; i++) {
    
    
            new Thread(()->{
    
    
                for (int i1 = 0; i1 < 1000; i1++) {
    
    
                    add();
                }
            }).start();
        }

        while(Thread.activeCount()>2){
    
    
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+" "+num);
    }
}

通过命令 javap -c VDemon2 把VDemon2的class文件反编译成字节码文件可以看出,为什么 num++ 只有一行,但是它却可以被多个线程同时操作。

在这里插入图片描述

2.1、如果不加 lock 和 synchronized,怎样保证原子性

可以使用原子类来解决

package com.zkw.JUC并发编程.tvolatile;

import java.util.concurrent.atomic.AtomicInteger;

//不保证原子性
public class VDemon2 {
    
    
    private volatile static AtomicInteger num = new AtomicInteger();
    public  static void add(){
    
    
        //num++ //不是一个原子性操作
        num.getAndIncrement(); //AtomicInteger +1 方法
    }

    public static void main(String[] args) {
    
    
        for (int i = 1; i <= 20; i++) {
    
    
            new Thread(()->{
    
    
                for (int i1 = 0; i1 < 1000; i1++) {
    
    
                    add();
                }
            }).start();
        }

        while(Thread.activeCount()>2){
    
    
            Thread.yield();
        }
        System.out.println(Thread.currentThread().getName()+" "+num);
    }
}

3、指令重排

volatile可以避免指令重排:

内存屏障,CPU指令,作用:

1、保证特定的操作的执行顺序!

2、可以保证某些变量的内存可见性(利用这些特性volatile实现了可见性)

在这里插入图片描述

Volatile 是可以保持 可见性。不能保证原子性,由于内存屏障,可以保证避免指令重排现象产生

猜你喜欢

转载自blog.csdn.net/fgets__/article/details/120794698