@@ -53,42 +53,40 @@ slowdown occurs):
53
53
54
54
同时在多个位置完成多任务。这解决了所谓的 CPU 密集型问题:将程序分为多部分,在多个处理器上同时处理不同部分来加快程序执行效率。
55
55
56
- 上面的定义告诉了我们术语令人困惑的原因:两者的核心是 “同时完成多个任务”。并行增加了跨多个处理器的分布。 更重要的是,这两种方法可以解决不同类型的问题:解决I / O绑定问题和并行化可能对您没有任何好处,因为该问题不是整体速度,而是阻塞。采取计算约束问题并尝试在单个处理器上使用并发性解决问题可能会浪费时间 。两种方法都试图在更短的时间内完成更多工作,但是它们实现加速的方式却有所不同,并且取决于问题所施加的约束 。
56
+ 上面的定义说明了这两个术语令人困惑的原因:两者的核心都是 “同时完成多个任务”,不过并行增加了跨多个处理器的分布。 更重要的是,它们可以解决不同类型的问题:并行可能对解决I / O密集型问题没有任何好处,因为问题不在于程序的整体执行速度,而在于I/O阻塞。而尝试在单个处理器上使用并发来解决计算密集型问题也可能是浪费时间 。两种方法都试图在更短的时间内完成更多工作,但是它们实现加速的方式有所不同,这取决于问题施加的约束 。
57
57
58
+ 这两个概念混合在一起的一个主要原因是包括Java在内的许多编程语言使用相同的机制 - ** 线程** 来实现并发和并行。
58
59
59
- 术语混淆的原因在上面的定义中显示:其中核心是“在同一时间完成多个任务。”并行性通过多个处理器增加分布。更重要的是,两者解决了不同类型的问题:解决I/O密集型问题,并行化可能对你没有任何好处,因为问题不是整体速度,而是阻塞。并且考虑到计算力限制问题并试图在单个处理器上使用并发来解决它可能会浪费时间。两种方法都试图在更短的时间内完成更多,但它们实现加速的方式是不同的,并且取决于问题所带来的约束。
60
+ 我们甚至可以尝试以更细的粒度去进行定义(然而这并不是标准化的术语):
60
61
61
- 这两个概念混合在一起的一个主要原因是包括Java在内的许多编程语言使用相同的机制** 线程** 来实现并发和并行。
62
-
63
- 我们甚至可以尝试添加细致的粒度去定义(但是,这不是标准化的术语):
64
-
65
- - ** 纯并发** :任务仍然在单个CPU上运行。纯并发系统产生的结果比顺序系统更快,但如果有更多的处理器,则运行速度不会更快
66
- - ** 并发-并行** :使用并发技术,结果程序利用更多处理器并更快地生成结果
62
+ - ** 纯并发** :仍然在单个CPU上运行任务。纯并发系统比顺序系统更快地产生结果,但是它的运行速度不会因为处理器的增加而变得更快。
63
+ - ** 并发-并行** :使用并发技术,结果程序可以利用更多处理器更快地产生结果。
67
64
- ** 并行-并发** :使用并行编程技术编写,如果只有一个处理器,结果程序仍然可以运行(Java 8 ** Streams** 就是一个很好的例子)。
68
65
- ** 纯并行** :除非有多个处理器,否则不会运行。
69
66
70
67
在某些情况下,这可能是一个有用的分类法。
71
68
72
- 对并发性的语言和库支持似乎 [ Leaky Abstraction] ( https://en.wikipedia.org/wiki/Leaky_abstraction ) 是完美候选者 。抽象的目标是“抽象出”那些对于手头想法不重要的东西,从不必要的细节中汲取灵感。如果抽象是漏洞,那些碎片和细节会不断重新声明自己是重要的,无论你试图隐藏它们多少
69
+ 支持并发性的语言和库似乎是 [ 抽象泄露( Leaky Abstraction) ] ( https://en.wikipedia.org/wiki/Leaky_abstraction ) 一词的完美候选 。抽象的目标是“抽象出”那些对于手头想法不重要的东西,以屏蔽不必要的细节。如果抽象是有漏洞的,那些碎片和细节就会不断重新声明自己是重要的,无论你废了多少功夫来隐藏它们。
73
70
74
- 我开始怀疑是否真的有高度抽象。当编写这些类型的程序时,你永远不会被底层系统和工具屏蔽,甚至关于CPU缓存如何工作的细节 。最后,如果你非常小心,你创作的东西在特定的情况下起作用,但它在其他情况下不起作用。有时,区别在于两台机器的配置方式,或者程序的估计负载 。这不是Java特有的-它是并发和并行编程的本质 。
71
+ 我开始怀疑是否真的有高度抽象。因为当编写这类程序时,底层的系统、工具,甚至是关于CPU缓存如何工作的细节,都永远不会被屏蔽 。最后,如果你非常小心,你创作的东西在特定的情况下工作,但在其他情况下不工作。有时是两台机器的配置方式不同,有时是程序的估计负载不同 。这不是Java特有的 - 这是并发和并行编程的本质 。
75
72
76
- 你可能会认为[ 纯函数式] ( https://en.wikipedia.org/wiki/Purely_functional ) 语言没有这些限制。实际上,纯函数式语言解决了大量并发问题,所以如果你正在解决一个困难的并发问题,你可以考虑用纯函数语言编写这个部分。但最终,如果你编写一个使用队列的系统,例如,如果它没有正确调整并且输入速率要么没有被正确估计或被限制(并且限制意味着,在不同情况下不同的东西具有不同的影响),该队列将填满并阻塞或溢出 。最后,你必须了解所有细节,任何问题都可能会破坏你的系统。这是一种非常不同的编程方式
73
+ 你可能会认为[ 纯函数式] ( https://en.wikipedia.org/wiki/Purely_functional ) 语言没有这些限制。实际上,纯函数式语言解决了大量并发问题,所以如果你正在解决一个困难的并发问题,你可以考虑用纯函数语言编写这个部分。但最终,如果你编写一个使用队列的系统,例如,如果该系统没有被正确地调整,并且输入速率也没有被正确地估计或限制(在不同的情况下,限制意味着具有不同的影响的不同东西),该队列要么被填满并阻塞,要么溢出 。最后,你必须了解所有细节,任何问题都可能会破坏你的系统。这是一种非常不同的编程方式。
77
74
78
75
<!-- A New Definition ofConcurrencyFor -->
79
76
### 并发的新定义
80
77
81
78
几十年来,我一直在努力解决各种形式的并发问题,其中一个最大的挑战一直是简单地定义它。在撰写本章的过程中,我终于有了这样的洞察力,我认为可以定义它:
82
79
> ** 并发性是一系列性能技术,专注于减少等待**
83
80
84
- 这实际上是一个相当多的声明 ,所以我将其分解:
81
+ 这实际上是一个相当复杂的表述 ,所以我将其分解:
85
82
86
- - 这是一个技术类集合 :包含许多不同的方法来解决这个问题。这是使定义并发性如此具有挑战性的问题之一,因为技术差别很大
83
+ - 这是一个集合 :包含许多不同的方法来解决这个问题。这是使定义并发性如此具有挑战性的问题之一,因为技术差异很大。
87
84
- 这些是性能技术:就是这样。并发的关键点在于让你的程序运行得更快。在Java中,并发是非常棘手和困难的,所以绝对不要使用它,除非你有一个重大的性能问题 - 即使这样,使用最简单的方法产生你需要的性能,因为并发很快变得无法管理。
88
- - “减少等待”部分很重要而且微妙。无论(例如)你运行多少个处理器,你只能在等待某个地方时产生结果 。如果你发起I/O请求并立即获得结果,没有延迟,因此无需改进。如果你在多个处理器上运行多个任务,并且每个处理器都以满容量运行,并且任何其他任务都没有等待 ,那么尝试提高吞吐量是没有意义的。并发的唯一形式是如果程序的某些部分被迫等待 。等待可以以多种形式出现 - 这解释了为什么存在如此不同的并发方法。
85
+ - “减少等待”部分很重要而且微妙。无论(例如)你运行多少个处理器,你只能在等待发生时产生效益 。如果你发起I/O请求并立即获得结果,没有延迟,因此无需改进。如果你在多个处理器上运行多个任务,并且每个处理器都以满容量运行,并且没有任务需要等待其他任务 ,那么尝试提高吞吐量是没有意义的。并发的唯一机会是如果程序的某些部分被迫等待 。等待可以以多种形式出现 - 这解释了为什么存在如此不同的并发方法。
89
86
90
- 值得强调的是,这个定义的有效性取决于等待这个词 。如果没有什么可以等待,那就没有机会了 。如果有什么东西在等待,那么就会有很多方法可以加快速度,这取决于多种因素,包括系统运行的配置,你要解决的问题类型以及其他许多问题。
87
+ 值得强调的是,这个定义的有效性取决于“等待”这个词 。如果没有什么可以等待,那就没有机会去加速 。如果有什么东西在等待,那么就会有很多方法可以加快速度,这取决于多种因素,包括系统运行的配置,你要解决的问题类型以及其他许多问题。
91
88
<!-- Concurrency Superpowers -->
89
+
92
90
## 并发的超能力
93
91
94
92
想象一下,你置身于一部科幻电影。你必须在高层建筑中搜索一个精心巧妙地隐藏在建筑物的一千万个房间之一中的单个物品。你进入建筑物并沿着走廊向下移动。走廊分开了。
0 commit comments