《七周七并发模型》章节试读

出版日期:2015-3
ISBN:9787115386064
作者:Paul Butcher
页数:244页

《七周七并发模型》的笔记-第6页 - 概述

##并发还是并行
##并行架构,现在计算机的多层次并行

《七周七并发模型》的笔记-第1页 - all

七周七并发模型 (图灵程序设计丛书), 【美】Paul Butcher
并发程序含有多个逻辑上的独立执行块4,它们可以独立地并行执行,也可以串行执行。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 240-241
差异:并发是问题域中的概念——程序需要被设计成能够处理多个同时(或者几乎同时)发生的事件;而并行则是方法域中的概念——通过将问题中的多个部分并行执行,来加速解决问题。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 248-250
并发和并行经常被混淆的原因之一是,传统的“线程与锁”模型并没有显式支持并行。如果要用线程与锁模型为多核进行开发,唯一的选择就是写一个并发的程序,并行地运行在多核上。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 267-269
位级(bit-level)并行 为什么32位计算机的运行速度比8位计算机更快?因为并行。对于两个32位数的加法,8位计算机必须进行多次8位计算,而32位计算机可以一步完成,即并行地处理32位数的4字节。 计算机的发展经历了8位、16位、32位,现在正处于64位时代。然而由位升级带来的性能改善是存在瓶颈的,这也正是短期内我们无法步入128位时代的原因。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 277-281
指令级(instruction-level)并行 现代CPU的并行度很高,其中使用的技术包括流水线、乱序执行和猜测执行等。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 281-283
数据级(data)并行 数据级并行(也称为“单指令多数据”,SIMD)架构,可以并行地在大量数据上施加同一操作。这并不适合解决所有问题,但在适合的场景却可以大展身手。 图像处理就是一种适合进行数据级并行的场景。比如,为了增加图片亮度就需要增加每一个像素的亮度。现代GPU(图形处理器)也因图像处理的特点而演化成了极其强大的数据并行处理器。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 288-292
任务级(task-level)并行 终于来到了大家所认为的并行形式——多处理器。从程序员的角度来看,多处理器架构最明显的分类特征是其内存模型(共享内存模型或分布式内存模型)。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 292-294
使用并发的目的,不仅仅是为了让程序并行运行从而发挥多核的优势。若正确使用并发,程序还将获得以下优点:及时响应、高效、容错、简单。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 305-306
为了增强软件的容错性,并发代码的关键是独立性和故障检测。独立性是指一个故障不会影响到故障任务以外的其他任务。故障检测是指当一个任务失败时(原因可能是任务崩溃、失去响应或硬件故障),需要通知负责故障处理的其他任务来处理。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 323-325
这个模型适用于解决并发问题、并行问题,还是两者皆可?
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 352-353
这个模型适用于哪种并行架构? 这个模型是否有利于我们写出容错性强的代码,或用于解决分布式问题的代码?
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 353-355
线程与锁模型其实是对底层硬件运行过程的形式化。这种形式化既是该模型最大的优点,也是它最大的缺点。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 361-362
并发编程中如果某事可能会发生,那么不论多艰难它一定会发生,而且可能发生在最不利的时刻)。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 412-413
Java内存模型定义了何时一个线程对内存的修改对另一个线程可见1。基本原则是,如果读线程和写线程不进行同步,就不能保证可见性。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 505-506
一个线程想使用多把锁时,就需要考虑死锁的可能。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 554-555
唯一的解决思路是避免持有锁时调用外星方法。一种方法是在遍历之前对listeners进行保护性复制(defensive copy),再针对这份副本进行遍历:
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 607-609
一些帮助我们避免危害的准则: 对共享变量的所有访问都需要同步化; 读线程和写线程都需要同步化; 按照约定的全局顺序来获取多把锁; 当持有锁时避免调用外星方法; 持有锁的时间应尽可能短。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 624-629
一个线程因为等待内置锁而进入阻塞之后,就无法中断该线程了; 尝试获取内置锁时,无法设置超时; 获得内置锁,必须使用synchronized块。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 646-649
声明synchronized的函数其实只是个“语法糖”,其等价于将函数体按以下形式进行包装: synchronized(this) { «函数体» }
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 652-655
这段代码中,使用try ... finally是个很好的实践,无论被锁保护的代码发生了什么,都可以确保锁会被释放。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 664-665
有一些方法可以减小活锁的几率。比如为每个线程设置不同的超时时间,来减少所有线程同时超时的几率。但通过设置超时来处理死锁不能说是一个好的方案——以后我们还可以做得更好。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 734-735
当另一个线程调用了signal()或signalAll(),意味着对应的条件可能变为真,await()将原子地恢复运行并重新加锁。需要注意的是当await()函数返回时,只意味着等待的条件可能为真。这就是为什么要在一个循环中调用await()的原因——从await()返回后,需要重新检查等待的条件是否为真,必要的话可能再次调用await()并阻塞。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 804-811
需要注意的是当await()函数返回时,只意味着等待的条件可能为真。这就是为什么要在一个循环中调用await()的原因——从await()返回后,需要重新检查等待的条件是否为真,必要的话可能再次调用await()并阻塞。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 807-811
与锁相比,使用原子变量有诸多好处。首先,我们不会忘了在正确的时候获取锁。例如,因getCount()忘了同步而引发的Counter内存可见性的问题将不会发生。其次,由于没有锁的参与,对原子变量的操作不会引发死锁。 最后,原子变量是无锁(lock-free)非阻塞(non-blocking)算法的基础,这种算法可以不用锁和阻塞来达到同步的目的。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 866-871
volatile是一种低级形式的同步。它并不能解决Counter的问题(
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 879-880
因为将count标记成volatile并不能保证count++操作是原子的。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 881-882
int threadPoolSize = Runtime.getRuntime().availableProcessors() * 2;
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 947-948
话虽如此,但也存在经验法则:对于CPU密集型的任务,线程池大小应接近于可用核数;对于IO密集型的任务,线程池可以设置得更大些。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 979-980
的ConcurrentHashMap正是我们所需要的。它不仅提供了原子的读-改-写方法,还使用了更高级的并发访问(被称为锁分段(lock striping)技术)7。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 1110-1112
更容易,而且在以下方面让程序更安全高效: 使用线程池,而不直接创建线程; 使用CopyOnWriteArrayList让监听器相关的代码更简单高效; 使用ArrayBlockingQueue让生产者和消费者之间高效协作; ConcurrentHashMap提供了更好的并发访问。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 1206-1212
Java Concurrency in Practice
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 1272-1272
使用future模型的一个典型场景是与其他服务器之间的通信。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2115-2116
函数式编程中的函数具有引用透明性。利用这个特性可以安全地对函数的求值顺序进行调整,而不会影响到程序的运行。值得一提的是,利用这个特性可以让代码在其所依赖的数据被准备好时才可运行,这也称为数据流式编程(Clojure提供future模型和promise模型对其进行支持)。我们还通过一个例子,用数据流式编程简化了Web服务的实现。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2169-2172
很多人认为函数式代码比起等价的命令式代码效率较低。对于某些场景确实存在性能损失,但大部分场景性能损失是远低于预期的。而且用少许性能损失来换取程序健壮性和扩展性的提升是值得的。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2212-2214
Clojure的数据结构是持久的,因此这段代码才是线程安全的。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2316-2317
持久数据结构 我们这里说的“持久”并不是指将数据持久化到磁盘或者保存到数据库中,而是指数据结构被修改时总是保留其之前的版本,这样可以为代码提供一致的数据视角。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2318-2319
幸运的是,持久数据结构的实现选择了更精巧的方法,其中使用了共享结构。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2326-2327
赫拉克利特(Heraclitus)是这样描述这个现象的: 我们不能两次踏入同一条河流,因为水在不停地流动。 许多编程语言都错误地认为河流是不变的实体;而Clojure则认为河流是一直在改变的。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2374-2377
校验器是一个函数,当改变原子变量的值时就会调用它。如果校验器返回true,就允许这次修改,否则就放弃这次修改。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2395-2397
与校验器不同,监视器是在原子变量的值改变之后才被调用,且无论swap!重试多少次,监视器只会被调用一次。因此,监视器可以具有副作用。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2411-2413
可变数据类型:代理(agent)和引用(ref)。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2525-2525
引用(ref)比原子变量和代理更复杂,通过引用可以实现软件事务内存(Software Transactional Memory,STM)。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2633-2634
STM事务具有原子性、一致性和隔离
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2649-2649
STM的数据在电源故障或系统崩溃时会丢失。如果需要用到持久性,就必须使用数据库。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2656-2657
dosync包装的所有元素构成了一个事务。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2661-2662
事务需要保证没有副作用。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2681-2682
使用actor模型保留了可变状态,只是不进行共享。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 2990-2991
类似于Erlang,在Elixir中,actor对象被称为进程。大部分场景下,进程是一个重量级的概念,它会消耗很多资源,且创建代价很高。不过在Elixir中,进程是一个轻量级的概念,比操作系统级的线程还要轻量:它消耗更少的资源,且创建代价很低。Elixir程序可以毫无困难地创建数千个进程,通常不需要依赖线程池(参见2.4节)等技术。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3010-3013
Elixir实现了尾调用消除。尾调用消除指的是如果函数在最后调用了自己,那么递归调用将被替换成一个简单的跳转。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3074-3075
Elixir习惯用元组作为消息,且第一个元素表示消息处理是成功的还是失败的。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3177-3178
通过设置进程的:trap_exit标识,可以让一个进程捕获另一个进程的终止消息。用专业术语来说,这是将进程转化为系统进程:
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3385-3387
创建一个规模宏大且可生长的系统的关键在于其模块之间应该如何交流,而不在于其内部的属性和行为应该如何表现。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3872-3873
这段话也概括了使用actor模型进行编程的精髓——我们可以认为actor模型是面向对象模型在并发编程领域的扩展。actor模型精心设计了消息传输和封装的机制,强调了面向对象的精髓,
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3873-3875
类似于线程与锁模型,actor模型对并行也没有提供直接支持。需要通过并发的技术来构造并行的方案,这样就会引入不确定性。而且,由于多个actor并不共享状态,仅通过消息传递来进行交流,所以不太适合实施细粒度的并行。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3893-3895
:actor模型的重点在于参与交流的实体,而CSP模型的重点在于用于交流的通道。因此使用CSP模型将是另一番体验。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3907-3908
与actor模型类似,通信顺序进程(Communicating Sequential Processe,CSP)模型也是由独立的、并发执行的实体所组成,实体之间也是通过发送消息进行通信。但两种模型的重要差别是:CSP模型不关注发送消息的实体,而是关注发送消息时使用的channel(通道)。
【美】Paul Butcher, 七周七并发模型 (图灵程序设计丛书), loc. 3919-3921


 七周七并发模型下载


 

外国儿童文学,篆刻,百科,生物科学,科普,初中通用,育儿亲子,美容护肤PDF图书下载,。 零度图书网 

零度图书网 @ 2024