您的位置:首页 > Web前端

The Java™ Tutorials — Concurrency :Thread Interference 线程冲突

2016-02-11 18:59 429 查看


The Java™ Tutorials — Concurrency :Thread Interference 线程冲突

原文地址:https://docs.oracle.com/javase/tutorial/essential/concurrency/interfere.html


关键点

线程冲突的原因:并发环境下,非原子操作所带来的结果不确定性


全文翻译

Consider a simple class called Counter

看下下面这个名为Counter的简单类:

class Counter {
private int c = 0;

public void increment() {
c++;
}

public void decrement() {
c--;
}

public int value() {
return c;
}

}


Counter is designed so that each invocation of increment will add 1 to c, and each invocation of decrement will subtract 1 from c. However, if a Counter object is referenced from multiple threads, interference between threads may prevent this from happening
as expected.

Counter的设计是这样的,每次调用increment是都会对C加一,调用decrement都会为C减一。然而,如果一个Counter对象被多个线程引用,线程间的冲突就会阻止程序按照预期发展。

Interference happens when two operations, running in different threads, but acting on the same data, interleave. This means that the two operations consist of multiple steps, and the sequences of steps overlap.

当两个操作运行在不同的线程之中,但是针对同一个数据,且交错进行时,冲突就会发生。这也就是说两个操作包含了多个步骤,而且步骤间有重叠。

It might not seem possible for operations on instances of Counter to interleave, since both operations on c are single, simple statements. However, even simple statements can translate to multiple steps by the virtual machine. We won’t examine the specific
steps the virtual machine takes — it is enough to know that the single expression c++ can be decomposed into three steps:
Retrieve the current value of c.
Increment the retrieved value by 1.
Store the incremented value back in c.

看起来针对Counter实例的操作是不可能交错进行的,因为所有对c的操作都是单独的、简单的语句。然而,即使是简单的语句也可以被JVM翻译成多个步骤。我们不去查证JVM究竟进行了那些具体的步骤,知道一个简单的c++表达式可被分解成三步操作就足够了:
重新获取c的值
对获取的值加一
把新的值存回到c中去

The expression c– can be decomposed the same way, except that the second step decrements instead of increments.

c--
表达式也按照同样的规则被分解,不过第二步要把加改为减。

Suppose Thread A invokes increment at about the same time Thread B invokes decrement. If the initial value of c is 0, their interleaved actions might follow this sequence:
Thread A: Retrieve c.
Thread B: Retrieve c.
Thread A: Increment retrieved value; result is 1.
Thread B: Decrement retrieved value; result is -1.
Thread A: Store result in c; c is now 1.
Thread B: Store result in c; c is now -1.

假设线程A调用了increment而此时线程B也调用了decrement。如果c的初值为0,它们交错进行的操作也许是按照下面的节奏进行的:
线程A:获取c的值
线程B:获取c的值
线程A:对获取到的c值加一;结果为1
线程B:对获取到的c值减一;结果为-1
线程A:将结果存回到c;c现在是1
线程B:将结果存回到c;c现在是-1

Thread A’s result is lost, overwritten by Thread B. This particular interleaving is only one possibility. Under different circumstances it might be Thread B’s result that gets lost, or there could be no error at all. Because they are unpredictable, thread interference
bugs can be difficult to detect and fix.

线程A的结果丢掉了,被线程B的结果所覆盖。这个交错进行的顺序只是其中的一种可能。在不同情况下,线程B的结果可能被丢到了,或者可能根本也就不出错。由于这是不可预见的,线程冲突的缺陷很难检测与修复。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息