4. 共享模型之管程(4.1 共享带来的问题)

4.1 共享带来的问题

      • 1、Java 的体现
      • 2、问题分析
      • 3、临界区
      • 4、竞态条件

1、Java 的体现

两个线程对初始值为 0 的静态变量一个做自增,一个做自减,各做 5000 次,结果是 0 吗?

public class TestCounterUnsafe {
    static int counter = 0;

    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                counter++;
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                counter--;
            }
        }, "t2");

        t1.start();
        t2.start();
        t1.join();
        t2.join();
        log.debug("{}",counter);
    }
}

在这里插入图片描述

2、问题分析

以上的结果可能是正数、负数、零。为什么呢?因为 Java 中对静态变量的自增,自减并不是原子操作,从字节码来进行分析

例如对于 i++ 而言(i 为静态变量),实际会产生如下的 JVM 字节码指令:
4. 共享模型之管程(4.1 共享带来的问题)_第1张图片
多线程下这 8 行代码可能交错运行:

出现负数的情况:
4. 共享模型之管程(4.1 共享带来的问题)_第2张图片

出现正数的情况:
4. 共享模型之管程(4.1 共享带来的问题)_第3张图片

3、临界区

  • 一个程序运行多个线程本身是没有问题的
    • 问题出在多个线程访问共享资源
    • 多个线程读共享资源其实也没有问题
  • 在多个线程对共享资源读写操作时发生指令交错,就会出现问题
  • 一段代码块内如果存在对共享资源的多线程读写操作,称这段代码块为临界区

4、竞态条件

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

你可能感兴趣的:(Java多线程,java多线程)