附录:并发底层原理 翻译至原子类

This commit is contained in:
AlfredAlan
2019-07-25 01:20:05 +08:00
parent 748c99c636
commit 6d5922dda5

View File

@@ -694,7 +694,7 @@ public class ReOrdering implements Runnable {
如果你尝试使用 **volatile** ,你可能更应该尝试让一个变量线程安全而不是引起同步的成本。因为 **volatile** 使用起来非常微妙和棘手,所以我建议根本不要使用它;相反,请使用本附录后面介绍的 **java.util.concurrent.atomic** 里面类之一。它们以比同步低得多的成本提供了完全的线程安全性。
如果正在尝试调试其他人的并发代码,请首先查找使用 **volatile** 的代码并将其替换为**Atomic** 变量。除非你确定程序员对并发性有很高的理解,否则它们很可能会误用 **volatile**
如果正在尝试调试其他人的并发代码,请首先查找使用 **volatile** 的代码并将其替换为**Atomic** 变量。除非你确定程序员对并发性有很高的理解,否则它们很可能会误用 **volatile**
<!-- Atomicity -->
## 原子性
@@ -861,7 +861,7 @@ No failures found
只有并发编程专家有能力去尝试做像前面例子情况的优化;再次强调,请遵循 Brain 的同步法则。
### Josh 的序列数字
### Josh 的序列
作为第二个示例,考虑某些更简单的东西:创建一个产生序列号的类,灵感启发于 Joshua Bloch 的 *Effective Java Programming Language Guide* (Addison-Wesley 出版社, 2001) 第 190 页。每次调用 `nextSerialNumber()` 都必须返回唯一值。
@@ -992,6 +992,82 @@ No duplicates detected
### 原子类
Java 5 引入了专用的原子变量类,例如 **AtomicInteger**、**AtomicLong**、**AtomicReference** 等。这些提供了原子性升级。这些快速、无锁的操作,它们是利用了现代处理器上可用的机器级原子性。
下面,我们可以使用 **atomicinteger** 重写 **unsafereturn.java** 示例:
```java
// lowlevel/AtomicIntegerTest.java
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.*;
import onjava.*;
public class AtomicIntegerTest extends IntTestable {
private AtomicInteger i = new AtomicInteger(0);
public int getAsInt() { return i.get(); }
public void evenIncrement() { i.addAndGet(2); }
public static void main(String[] args) {
Atomicity.test(new AtomicIntegerTest());
}
}
/* Output:
No failures found
*/
```
现在,我们通过使用 **AtomicInteger** 来消除了 **synchronized** 关键字。
下面使用 **AtomicInteger** 来重写 **SynchronizedEvenProducer.java** 示例:
```java
// lowlevel/AtomicEvenProducer.java
// Atomic classes: occasionally useful in regular code
import java.util.concurrent.atomic.*;
public class AtomicEvenProducer extends IntGenerator {
private AtomicInteger currentEvenValue =
new AtomicInteger(0);
@Override
public int next() {
return currentEvenValue.addAndGet(2);
}
public static void main(String[] args) {
EvenChecker.test(new AtomicEvenProducer());
}
}
/* Output:
No odd numbers discovered
*/
```
再次,使用 **AtomicInteger** 消除了对所有其他同步方式的需要。
下面是一个使用 **AtomicInteger** 实现 **SerialNumbers** 的例子:
```java
// lowlevel/AtomicSerialNumbers.java
import java.util.concurrent.atomic.*;
public class
AtomicSerialNumbers extends SerialNumbers {
private AtomicInteger serialNumber =
new AtomicInteger();
public synchronized int nextSerialNumber() {
return serialNumber.getAndIncrement();
}
public static void main(String[] args) {
SerialNumberChecker.test(
new AtomicSerialNumbers());
}
}
/* Output:
No duplicates detected
*/
```
这些都是对单一字段的简单示例; 当你创建更复杂的类时,你必须确定哪些字段需要保护,在某些情况下,你可能仍然最后在方法上使用 **synchronized** 关键字。
<!-- Critical Sections -->
## 临界区