# 线程干扰

> 原文： [https://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html](https://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html)

考虑一个名为 [``Counter``](examples/Counter.java)的简单类

```
class Counter {
    private int c = 0;

    public void increment() {
        c++;
    }

    public void decrement() {
        c--;
    }

    public int value() {
        return c;
    }

}

```

`Counter`的设计使得`increment`的每次调用都会将[1]添加到`c`，`decrement`的每次调用都会从`c`中减去 1。但是，如果从多个线程引用`Counter`对象，则线程之间的干扰可能会阻止这种情况按预期发生。

当两个操作在不同的线程中运行但作用于相同的数据时，会发生干扰 _interleave_ 。这意味着这两个操作由多个步骤组成，并且步骤序列重叠。

对`Counter`实例的操作似乎不可能进行交错，因为`c`上的两个操作都是单个简单的语句。但是，即使是简单的语句也可以由虚拟机转换为多个步骤。我们不会检查虚拟机采取的具体步骤 - 足以知道单个表达式`c++`可以分解为三个步骤：

1.  检索`c`的当前值。
2.  将检索的值增加 1。
3.  将增加的值存储回`c`。

表达式`c--`可以以相同的方式分解，除了第二步减少而不是增量。

假设线程 A 在线程 B 调用`decrement`的同时调用`increment`。如果`c`的初始值为`0`，则它们的交错操作可能遵循以下顺序：

1.  线程 A：检索 c。
2.  线程 B：检索 c。
3.  线程 A：增加检索值;结果是 1。
4.  线程 B：减少检索值;结果是-1。
5.  线程 A：将结果存储在 c; c 现在是 1。
6.  线程 B：将结果存储在 c 中; c 现在是-1。

线程 A 的结果丢失，被线程 B 覆盖。这种特殊的交错只是一种可能性。在不同情况下，可能是线程 B 的结果丢失，或者根本没有错误。因为它们是不可预测的，所以难以检测和修复线程干扰错误。