首页 > 图书中心 > .NET并发编程实战

目录

目    录

 

 第Ⅰ部分  函数式编程在并发程序中所体现的优势 

第1章  函数式并发基础   3

1.1  你将从本书中学到什么   4

1.2  让我们从术语开始   5

1.2.1  顺序编程——一次执行一个任务   6

1.2.2  并发编程——同时运行多个任务   7

1.2.3  并行编程——同时执行多个任务   8

1.2.4  多任务处理——同时在一段时间内执行多个任务   9

1.2.5  多线程性能调优   10

1.3  为什么需要并发   11

1.4  并发编程的陷阱   14

1.4.1  并发的危害   14

1.4.2  共享状态的演变   17

1.4.3  一个简单的真实示例:并行快速排序   17

1.4.4  F#中的基准测试   21

1.5  为什么选择函数式编程实现并发   21

1.6  拥抱函数式范式   24

1.7  为什么选择F#和C#进行函数式并发编程   25

1.8  本章小结   27

第2章  并发函数式编程技术   29

2.1  使用函数组合解决复杂的问题   30

2.1.1  C#的函数组合   30

2.1.2  F#的函数组合   32

2.2  闭包简化函数式思考   33

2.2.1  使用lambda表达式捕获闭包中的变量   34

2.2.2  多线程环境中的闭包   36

2.3  用于程序加速的记忆化缓存技术   38

2.4  记忆快速网络爬虫的操作   42

2.5  延迟记忆化以获得更好的性能   46

2.6  有效率的并行推测以摊销昂贵计算成本   47

2.6.1  具有天然函数支持的预计算   50

2.6.2  使最佳计算获胜   51

2.7  延迟是件好事情   52

2.7.1  对严格求值语言并发行为的理解   52

2.7.2  延迟缓存技术和线程安全的单例模式   54

2.7.3  F#中的延迟支持   55

2.7.4  延迟和任务,一个强大的组合   55

2.8  本章小结   57

第3章  函数式数据结构和不可变性   59

3.1  真实世界的例子:捕猎线程不安全的对象   60

3.1.1  .NET不可变集合:一种安全的解决方案   63

3.1.2  .NET并发集合:更快的解决方案   67

3.1.3  代理消息传递模式:更快、更好的解决方案   69

3.2  在线程之间安全地共享函数式数据结构   72

3.3  修改的不可变性   73

3.3.1  数据并行的函数式数据结构   75

3.3.2  使用不可变性的性能影响   75

3.3.3  C#的不可变性   76

3.3.4  F#的不可变性   79

3.3.5  函数式列表:连接一条链中的单元格   80

3.3.6  构建可持久化数据结构:不可变二叉树   86

3.4  递归函数:一种自然的迭代方式   89

3.4.1  正确递归函数尾部:尾部调用优化   90

3.4.2  延续传递风格以优化递归函数   91

3.5  本章小结   95

 第Ⅱ部分  如何处理并发程序的不同部分 

第4章  处理大数据的基础:数据并行,第1部分   99

4.1  什么是数据并行   100

4.1.1  数据和任务并行   101

4.1.2  “尴尬并行”概念   102

4.1.3  .NET中的数据并行支持   102

4.2  Fork / Join模式:并行Mandelbrot   103

4.2.1  当GC是瓶颈时:结构与类对象   109

4.2.2  并行循环的缺点   111

4.3  测量性能速度   111

4.3.1  Amdahl定律定义了性能改进的极限   112

4.3.2  Gustafson定律:进一步衡量性能改进   113

4.3.3  并行循环的局限性:素数之和   113

4.3.4  简单循环可能会出现什么问题   115

4.3.5  声明式并行编程模型   117

4.4  本章小结   118

第5章  PLINQ和MapReduce:数据并行,第2部分   121

5.1  PLINQ简介   122

5.1.1  PLINQ如何更具函数式   123

5.1.2  PLINQ和纯函数:并行字计数器   123

5.1.3  使用纯函数避免副作用   125

5.1.4  隔离和控制副作用:重构并行字计数器   127

5.2  并行聚合和归约数据   128

5.2.1  择伐(Deforesting):折叠的诸多优点之一   130

5.2.2  PLINQ中的fold:Aggregate函数   131

5.2.3  为PLINQ实现并行Reduce函数   137

5.2.4  F#的并行列表解析:PSeq   139

5.2.5  F#的并行数组   140

5.3  并行MapReduce模式   142

5.3.1  Map和Reduce函数   143

5.3.2  在NuGet 包库中使用 MapReduce   144

5.4  本章小结   149

第6章  实时事件流:函数式反应式编程   151

6.1  反应式编程: 大事件处理   152

6.2  用于反应式编程的.NET工具   155

6.2.1  事件组合器——更好的解决方案   156

6.2.2  .NET与F#组合器的互操作性   157

6.3  .NET中的反应式编程:反应式扩展(Rx)   160

6.3.1  从LINQ/PLINQ到Rx   162

6.3.2  IObservable:对偶IEnumerable   163

6.3.3  Action中的反应式扩展   164

6.3.4  Rx实时流   165

6.3.5  从事件到F# Observable   166

6.4  驯服事件流:使用Rx编程进行Twitter情绪分析   167

6.5  Rx发布者-订阅者   176

6.5.1  为强大的发布者-订阅者集线器使用Subject类型   176

6.5.2  与并发相关的Rx   177

6.5.3  实现可重用的Rx发布者-订阅者   178

6.5.4  使用Rx Pub-Sub类分析推文情绪   180

6.5.5  action中的观察者   183

6.5.6  方便的F#对象表达式   184

6.6  本章小结   184

第7章  基于任务的函数式并行   187

7.1  任务并行的简短介绍   188

7.1.1  为什么要进行任务并行和函数式编程   189

7.1.2  .NET中的任务并行化支持   189

7.2  .NET任务并行库   191

7.3  C# void的问题   196

7.4  延续传递风格(CPS):函数式控制流程   198

7.4.1  为什么要利用CPS   199

7.4.2  等待任务完成:延续模型   200

7.5  组合任务操作的策略   205

7.5.1  使用数学模式以获得更好的组合   207

7.5.2  任务使用准则   212

7.6  并行函数式管道模式   212

7.7  本章小结   218

第8章  最终胜出的任务异步模型   219

8.1  异步编程模型(APM)   220

8.1.1  异步编程的价值   220

8.1.2  可扩展性和异步编程   223

8.1.3  CPU密集型和I/O密集型操作   223

8.2  异步编程不受限制的并行度   224

8.3  .NET的异步支持   225

8.3.1  异步编程会破坏代码结构   228

8.3.2  基于事件的异步编程   228

8.4  C#基于任务的异步编程   229

8.4.1  匿名异步lambda   232

8.4.2  Task<T>是一个monadic容器   232

8.5  基于任务的异步编程:案例研究   235

8.5.1  异步取消   240

8.5.2  带有monadic Bind运算符的基于任务的异步组合   244

8.5.3  延迟异步计算以实现组合   245

8.5.4  如果出现问题,请重试   246

8.5.5  异步操作的错误处理   247

8.5.6  股票市场历史的异步并行处理   249

8.5.7  任务完成后的异步股票市场并行处理   251

8.6  本章小结   252

第9章  F#的异步函数编程   253

9.1  异步函数式方面   254

9.2  什么是F#异步工作流   254

9.2.1  计算表达式中的延续传递风格   254

9.2.2  异步工作流操作:Azure Blob存储并行操作   257

9.3  异步计算表达式   261

9.3.1  计算表达式和单子之间的区别   263

9.3.2  异步重试:生成自己的计算表达式   264

9.3.3  扩展异步工作流   266

9.3.4  映射异步操作:Async.map函子   267

9.3.5  并行化异步工作流:Async.Parallel   269

9.3.6  异步工作流取消支持   274

9.3.7  驯服并行异步操作   276

9.4  本章小结   280

第10章  用于流畅式并发编程的函数式组合器   281

10.1  执行流并不总是处于正常情况:错误处理   282

10.2  错误组合器:C#中的Retry、Otherwise和Task.Catch   285

10.2.1  FP中的错误处理:流控制的异常   289

10.2.2  在C#中使用Task<Option<T>>处理错误   291

10.2.3  F# AsyncOption类型:组合Async和Option   291

10.2.4  F#惯用的函数式异步错误处理   292

10.2.5  使用Result类型保留异常语义   294

10.3  在异步操作中控制异常   298

10.3.1  F#使用Async和Result 建模错误处理   302

10.3.2  使用monadic运算符bind扩展F# AsyncResult类型   304

10.4  使用函数式组合器抽象化操作   308

10.5  函数式组合器概要   309

10.5.1  TPL内置异步组合器   310

10.5.2  利用Task.WhenAny组合器实现冗余和交叉   311

10.5.3  使用Task.WhenAll组合器进行异步for-each   312

10.5.4  回顾迄今看到的数学模式   314

10.6  最终的并行组合应用函子   317

10.6.1  使用应用函子运算符扩展F#异步工作流   324

10.6.2  带有中缀运算符的F#应用函子语义   326

10.6.3  利用应用函子实现异构并行计算   326

10.6.4  组合和执行异构并行计算   328

10.6.5  使用条件异步组合器控制流   330

10.6.6  运用异步组合器   334

10.7  本章小结   336

第11章  使用代理应用反应式编程   339

11.1  什么是反应式编程   340

11.2  异步消息传递编程模型   342

11.2.1  消息传递和不可变性的关系   344

11.2.2  天然隔离   344

11.3  代理是什么   345

11.3.1  代理的组件   346

11.3.2  代理可以做什么   347

11.3.3  无锁并发编程的无共享方法   347

11.3.4  基于代理的编程如何体现函数式思想   348

11.3.5  代理是面向对象的   349

11.4  F#代理:MailboxProcessor   349

11.5  使用F# MailboxProcessor避免数据库瓶颈   352

11.5.1  MailboxProcessor消息类型:可区分联合   355

11.5.2  MailboxProcessor双向通信   356

11.5.3  在C#中使用AgentSQL   357

11.5.4  成组协调代理来并行工作流   358

11.5.5  如何使用F# MailboxProcessor处理错误   360

11.5.6  停止MailboxProcessor代理——CancellationToken   361

11.5.7  使用MailboxProcessor分发工作   362

11.5.8  使用代理缓存操作   364

11.5.9  由MailboxProcessor报告结果   368

11.5.10  使用线程池报告来自MailboxProcessor的事件   371

11.6  F# MailboxProcessor:10 000个代理的生命游戏   371

11.7  本章小结   376

第12章  使用TPL Dataflow的并行工作流与代理编程   379

12.1  TPL Dataflow的强大性   380

12.2  组合式设计:TPL Dataflow块   381

12.2.1  使用BufferBlock<TInput>作为FIFO缓冲区   382

12.2.2  使用TransformBlock<TInput, TOutput>转换数据   383

12.2.3  使用ActionBlock<TInput>完成工作   384

12.2.4  连接数据流块   385

12.3  使用TDF实现复杂的生产者/消费者   386

12.3.1  多生产者/单消费者模式   386

12.3.2  单生产者/多消费者模式   387

12.4  使用TPL Dataflow在C#中启用代理模型   388

12.4.1  代理折叠状态和消息:聚合   392

12.4.2  代理交互:并行单词计数器   392

12.5  压缩和加密大型流的并行工作流   397

12.5.1  上下文:处理大型数据流的问题   397

12.5.2  确保消息流的顺序完整性   402

12.5.3  连接、传播和完成   403

12.5.4  构建TDF工作流的规则   405

12.5.5  组合Reactive Extensions(Rx)和TDF   406

12.6  本章小结   407

 第Ⅲ部分  现代并发编程模式应用 

第13章  成功的并发编程的配方和设计模式   411

13.1  循环利用对象以减少内存消耗   412

13.2  自定义并行Fork/Join运算符   415

13.3  并行具有依赖关系的任务:设计代码以优化性能   418

13.4  用于协调并发I/O操作共享资源的闸门:一次写入,多次读取   423

13.5  线程安全的随机数生成器   430

13.6  多态事件聚合器   432

13.7  自定义Rx调度程序来控制并行度   435

13.8  并发的反应式可扩展客户端/服务器   438

13.9  可复用的自定义高性能并行filter-map运算符   448

13.10  无阻塞同步消息传递模型   452

13.11  使用代理编程模型协调并发作业   457

13.12  组合monadic函数   462

13.13  本章小结   465

第14章  使用并发函数式编程构建可扩展的移动应用程序   467

14.1  现实世界服务器上的函数式编程   468

14.2  如何设计一个成功的高性能应用程序   469

14.2.1  秘制酱:ACD   470

14.2.2  不同的异步模式:将工作排队以稍后执行   470

14.3  选择正确的并发编程模型   472

14.4  实时交易:股票市场示例的高层架构   475

14.5  股票市场应用程序的基本要素   479

14.6  编写股票市场交易应用程序   479

14.7  本章小结   501

附录A  函数式编程   503

附录B  F#概述   517

附录C  F#异步工作流和.NET Task之间的互操作性   535

版权所有(C)2023 清华大学出版社有限公司 京ICP备10035462号 京公网安备11010802042911号

联系我们 | 网站地图 | 法律声明 | 友情链接 | 盗版举报 | 人才招聘