From 6d5922dda57432b5ebf4893691c9953995156c7e Mon Sep 17 00:00:00 2001 From: AlfredAlan <854723360@mail.com> Date: Thu, 25 Jul 2019 01:20:05 +0800 Subject: [PATCH] =?UTF-8?q?=E9=99=84=E5=BD=95=EF=BC=9A=E5=B9=B6=E5=8F=91?= =?UTF-8?q?=E5=BA=95=E5=B1=82=E5=8E=9F=E7=90=86=20=E7=BF=BB=E8=AF=91?= =?UTF-8?q?=E8=87=B3=E5=8E=9F=E5=AD=90=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/book/Appendix-Low-Level-Concurrency.md | 80 ++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/docs/book/Appendix-Low-Level-Concurrency.md b/docs/book/Appendix-Low-Level-Concurrency.md index 857474c..85f074a 100644 --- a/docs/book/Appendix-Low-Level-Concurrency.md +++ b/docs/book/Appendix-Low-Level-Concurrency.md @@ -694,7 +694,7 @@ public class ReOrdering implements Runnable { 如果你尝试使用 **volatile** ,你可能更应该尝试让一个变量线程安全而不是引起同步的成本。因为 **volatile** 使用起来非常微妙和棘手,所以我建议根本不要使用它;相反,请使用本附录后面介绍的 **java.util.concurrent.atomic** 里面类之一。它们以比同步低得多的成本提供了完全的线程安全性。 -如果您正在尝试调试其他人的并发代码,请首先查找使用 **volatile** 的代码并将其替换为**Atomic** 变量。除非你确定程序员对并发性有很高的理解,否则它们很可能会误用 **volatile** 。 +如果你正在尝试调试其他人的并发代码,请首先查找使用 **volatile** 的代码并将其替换为**Atomic** 变量。除非你确定程序员对并发性有很高的理解,否则它们很可能会误用 **volatile** 。 ## 原子性 @@ -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** 关键字。 + ## 临界区