Skip to content

Commit 6d5922d

Browse files
committed
附录:并发底层原理 翻译至原子类
1 parent 748c99c commit 6d5922d

File tree

1 file changed

+78
-2
lines changed

1 file changed

+78
-2
lines changed

docs/book/Appendix-Low-Level-Concurrency.md

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ public class ReOrdering implements Runnable {
694694

695695
如果你尝试使用 **volatile** ,你可能更应该尝试让一个变量线程安全而不是引起同步的成本。因为 **volatile** 使用起来非常微妙和棘手,所以我建议根本不要使用它;相反,请使用本附录后面介绍的 **java.util.concurrent.atomic** 里面类之一。它们以比同步低得多的成本提供了完全的线程安全性。
696696

697-
如果您正在尝试调试其他人的并发代码,请首先查找使用 **volatile** 的代码并将其替换为**Atomic** 变量。除非你确定程序员对并发性有很高的理解,否则它们很可能会误用 **volatile**
697+
如果你正在尝试调试其他人的并发代码,请首先查找使用 **volatile** 的代码并将其替换为**Atomic** 变量。除非你确定程序员对并发性有很高的理解,否则它们很可能会误用 **volatile**
698698

699699
<!-- Atomicity -->
700700
## 原子性
@@ -861,7 +861,7 @@ No failures found
861861

862862
只有并发编程专家有能力去尝试做像前面例子情况的优化;再次强调,请遵循 Brain 的同步法则。
863863

864-
### Josh 的序列数字
864+
### Josh 的序列号
865865

866866
作为第二个示例,考虑某些更简单的东西:创建一个产生序列号的类,灵感启发于 Joshua Bloch 的 *Effective Java Programming Language Guide* (Addison-Wesley 出版社, 2001) 第 190 页。每次调用 `nextSerialNumber()` 都必须返回唯一值。
867867

@@ -992,6 +992,82 @@ No duplicates detected
992992

993993
### 原子类
994994

995+
Java 5 引入了专用的原子变量类,例如 **AtomicInteger****AtomicLong****AtomicReference** 等。这些提供了原子性升级。这些快速、无锁的操作,它们是利用了现代处理器上可用的机器级原子性。
996+
997+
下面,我们可以使用 **atomicinteger** 重写 **unsafereturn.java** 示例:
998+
999+
```java
1000+
// lowlevel/AtomicIntegerTest.java
1001+
import java.util.concurrent.*;
1002+
import java.util.concurrent.atomic.*;
1003+
import java.util.*;
1004+
import onjava.*;
1005+
1006+
public class AtomicIntegerTest extends IntTestable {
1007+
private AtomicInteger i = new AtomicInteger(0);
1008+
public int getAsInt() { return i.get(); }
1009+
public void evenIncrement() { i.addAndGet(2); }
1010+
public static void main(String[] args) {
1011+
Atomicity.test(new AtomicIntegerTest());
1012+
}
1013+
}
1014+
/* Output:
1015+
No failures found
1016+
*/
1017+
```
1018+
1019+
现在,我们通过使用 **AtomicInteger** 来消除了 **synchronized** 关键字。
1020+
1021+
下面使用 **AtomicInteger** 来重写 **SynchronizedEvenProducer.java** 示例:
1022+
1023+
```java
1024+
// lowlevel/AtomicEvenProducer.java
1025+
// Atomic classes: occasionally useful in regular code
1026+
import java.util.concurrent.atomic.*;
1027+
1028+
public class AtomicEvenProducer extends IntGenerator {
1029+
private AtomicInteger currentEvenValue =
1030+
new AtomicInteger(0);
1031+
@Override
1032+
public int next() {
1033+
return currentEvenValue.addAndGet(2);
1034+
}
1035+
public static void main(String[] args) {
1036+
EvenChecker.test(new AtomicEvenProducer());
1037+
}
1038+
}
1039+
/* Output:
1040+
No odd numbers discovered
1041+
*/
1042+
```
1043+
1044+
再次,使用 **AtomicInteger** 消除了对所有其他同步方式的需要。
1045+
1046+
下面是一个使用 **AtomicInteger** 实现 **SerialNumbers** 的例子:
1047+
1048+
```java
1049+
// lowlevel/AtomicSerialNumbers.java
1050+
import java.util.concurrent.atomic.*;
1051+
1052+
public class
1053+
AtomicSerialNumbers extends SerialNumbers {
1054+
private AtomicInteger serialNumber =
1055+
new AtomicInteger();
1056+
public synchronized int nextSerialNumber() {
1057+
return serialNumber.getAndIncrement();
1058+
}
1059+
public static void main(String[] args) {
1060+
SerialNumberChecker.test(
1061+
new AtomicSerialNumbers());
1062+
}
1063+
}
1064+
/* Output:
1065+
No duplicates detected
1066+
*/
1067+
```
1068+
1069+
这些都是对单一字段的简单示例; 当你创建更复杂的类时,你必须确定哪些字段需要保护,在某些情况下,你可能仍然最后在方法上使用 **synchronized** 关键字。
1070+
9951071
<!-- Critical Sections -->
9961072
## 临界区
9971073

0 commit comments

Comments
 (0)