4.0**. 共享带来的问题**

一个程序运行多个线程本身没有问题

问题出在多个线程访问共享资源

一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区

下面应用操作r变量,可以看作临界区

4.1 背景问题

两个线程一个加一个减带来的问题

public void test1() throws InterruptedException {
    Thread t1 = new Thread(() -> {
        for (int i = 0; i < 5000; i++) {
            r++;
        }
    });
    Thread t2 = new Thread(() -> {
        for (int i = 0; i < 5000; i++) {
            r--;
        }
    });
    t1.start();
    t2.start();
    t1.join();
    t2.join();
    System.out.println(r);
}

问题出现的原因:

例如对于 i++ 而言(i 为静态变量),实际会产生如下的 JVM 字节码指令:

Untitled

而 Java 的内存模型如下,完成静态变量的自增,自减需要在主存和工作内存中进行数据交换

Untitled

因此,如果线程2自减完,但是还没有写入,然后线程1操作完,线程2在写入,就会出现这样的问题。

多个线程在临界区内执行,由于代码的执行序列不同而导致结果无法预测,称之为发生了竞态条件

4.2 synchronized 解决方案

为了避免临界区的竞态条件发生,有多种手段可以达到目的。