第一章-请谈谈你对volatile的理解

是什么

volatile是Java虚拟机提供的轻量级的同步机制。

特性

  • 保证可见性
  • 不保证原子性
  • 禁止指令重排

JMM是什么

image-20191107101906130

image-20191107101934438

  1. 可见性

  2. 原子性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    /**
    * @desc volatile可见性、非原子性验证
    * @Author xw
    * @Date 2019/8/19
    */
    public class VolatileDemo {
    public static void main(String[] args) {
    // 验证可见性
    seeOkVisibility();
    // 验证非原子性
    seeNonAtomic();
    }

    private static void seeNonAtomic() {
    MyData myData = new MyData();
    for (int i = 1; i <= 100; i++) {
    new Thread(() -> {
    try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
    for (int j = 1; j <= 100 ; j++) {
    myData.addPlusPlus();
    }
    }, "T" + i).start();
    }
    while (Thread.activeCount() > 2) {

    }
    System.out.println(Thread.currentThread().getName() + "\t mission is over value:" + myData.number);
    }

    // 设置可见性
    private static void seeOkVisibility() {
    MyData myData = new MyData();
    new Thread(() -> {
    System.out.println(Thread.currentThread().getName() + "\t come in");
    try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
    myData.addTO60();
    System.out.println(Thread.currentThread().getName() + "\t updated number value: " + myData.number);
    }, "AAA").start();
    while (myData.number == 0) {

    }
    System.out.println(Thread.currentThread().getName() + "\t mission is over");
    }
    }

    class MyData {
    volatile int number;
    public void addTO60() {
    this.number = 60;
    }
    public void addPlusPlus() {
    this.number ++;
    }
    }
  1. 有序性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /**
    * @desc 指令重排
    * @Author xw
    * @Date 2019/8/8
    */
    public class ReSortSeqDemo {
    int a = 0;
    boolean flag = false;
    public void method01() {
    a = 1;
    flag = true;
    }

    // 多线程环境中线程交替执行,由于编译器优化重排的存在,两个线程中使用的变量能否保证一致性无法确定
    // JDK7以后做了优化
    public void method02() {
    if (flag){
    a = a + 5;
    }
    }

    public static void main(String[] args) {
    ReSortSeqDemo reSortSeqDemo = new ReSortSeqDemo();
    for(int i = 1; i <= 100; i++) {
    new Thread(() -> {
    reSortSeqDemo.method01();
    reSortSeqDemo.method02();
    System.out.println(Thread.currentThread().getName() + " change number to " + reSortSeqDemo.a);
    },"T" + i).start();
    }
    }
    }

你在哪些地方用到过volatile?

单例模式DCL代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/**
* @desc DCL单例 + volatile(禁止指令重排)
* @Author xw
* @Date 2019/8/20
*/
public class SingletonDemo {
private static volatile SingletonDemo instance = null;

private SingletonDemo() {
System.out.println(Thread.currentThread().getName() + "\t 我是构造方法");
}

public static SingletonDemo getInstance() {
if (instance == null) {
synchronized (SingletonDemo.class) {
if (instance == null) {
instance = new SingletonDemo();
}
}
}
return instance;
}

public static void main(String[] args) {
for (int i = 1; i < 100; i++) {
new Thread(() -> {
try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
SingletonDemo.getInstance();
}, "T" + i).start();
}
}
}

单例模式volatile分析

image-20191107102424436