Archive for ‘ July, 2013

深入理解并行编程-分割和同步设计(五)

原文链接    作者:paul    译者:谢宝友,鲁阳,陈渝

并行快速路径

细粒度的设计一般要比粗粒度的设计复杂。在许多情况,绝大部分开销只由一小部分代码产生[Knu73]。所以为什么不把精力放在这一小块代码上。

这就是并行快速路径设计模式背后的想法,尽可能地并行化常见情况下的代码路径,同时不产生并行化整个算法所带来的复杂性。您必须理解这一点,不只算法需要并行化,算法所属的工作负载也要并行化。构建这种并行快速路径,需要极大的创造性和设计上的努力。 Read more

深入理解并行编程-分割和同步设计(四)

原文链接    作者:paul    译者:谢宝友,鲁阳,陈渝

设计模式与锁粒度

图1.1:设计模式与锁粒度

图1.1是不同程度同步粒度的图形表示。每一种同步粒度都用一节内容来描述。下面几节主要关注锁,不过其他几种同步方式也有类似的粒度问题。

Read more

深入理解并行编程-分割和同步设计(三)

原文链接    作者:paul    译者:谢宝友,鲁阳,陈渝

设计准则

上面的章节中给出了三个并行编程的目标:性能、生产率和通用性。但是还需要更详细的设计准则来真正的指导真实世界中的设计,这就是本节将解决的任务。在真实世界中,这些准则经常在某种程度上冲突,这需要设计者小心的权衡得失。

这些准则可以被认为是设计中的阻力,对这些阻力进行恰当权衡,这就称为“设计模式”[Ale79],[GHJV95]。

基于三个并行编程目标的设计准则是加速、竞争、开销、读写比率和复杂性。 Read more

硬件的习性

原文链接    作者:paul    译者:谢宝友,鲁阳,陈渝

大多数人根据直觉就知道,在系统间传递消息要比在单个系统上执行简单计算更加耗时。不过,在共享同一块内存的系统的线程间传递消息是不是也更加耗时,这点可就不一定了。本章主要关注共享内存系统中的同步和通信的开销,只涉及了一些共享内存并行硬件设计的皮毛,想了解更多信息的读者,可以翻看Hennessy和Patterson的经典教材最新版[HP95]。

小问题4.1:为什么并行软件程序员需要如此痛苦地学习硬件的低级属性?如果只学习更高级些的抽象是不是更简单,更好,更通用?

Read more

软件事务内存导论

  1. 前言
  2. 软件事务内存
  3. 用Akka/Multiverse STM实现并发
  4. 创建事务
  5. 创建嵌套事务
  6. 配置Akka事务
  7. 阻塞事务
  8. 提交和回滚事件
  9. 集合与事务
  10. 处理写偏斜异常
  11. STM的局限性

软件事务内存导论(十一)-STM的局限性

声明:本文是《Java虚拟机并发编程》的第六章,感谢华章出版社授权并发编程网站发布此文,禁止以任何形式转载此文。

1.1    STM的局限性

STM消除了显式的同步操作,所以我们在写代码时就无需担心自己是否忘了进行同步或是否在错误的层级上进行了同步。然而STM本身也存在一些问题,比如在跨越内存栅栏失败或遭遇竞争条件时我们捕获不到任何有用的信息。我似乎可以听到你内心深处那个精明的程序员在抱怨“怎么会这样啊?”。确实,STM是有其局限性的,否则本书写到这里就应该结束了。STM只适用于写冲突非常少的应用场景,如果你的应用程序存在很多写操作竞争,那么我们就需要在STM之外寻找解决方案了。

下面让我们进一步讨论STM的局限性。STM提供了一种显式的锁无关编程模型,这种模型允许多个事务并发地运行,并且在没有发生冲突时所有事务都能毫无滞碍地运行,所以相对其他编程模型而言STM可以提供更好的并发性和线程安全方面的保障。当事务对相同对象或数据的写访问发生冲突时,只有一个事务能够顺利完成,其他事务都会被自动重做。这种重做机制延缓了写操作冲突时竞争失败的那些写者的执行,但却提升了读者和竞争操作的胜利者的执行速度。当对于相同对象的并发写操作不频繁时,其性能就不会受到太大影响。但是随着冲突的增多,程序整体性能将因此变得越来越差。
Read more

Mutex和内存可见性

原文链接  作者:Loïc  译者:林永听

介绍

POSIX线程遵守共享内存模型[1],此模型各线程可以访问一组共享对象。多个并发的线程需要协同访问共享对象。为此该模型引入了以下两个属性来简化程序设计:

  • 原子访问:避免线程在访问数据对象时,另一线程正在修改它。
  • 内存可见性:一旦线程修改数据对象,其它线程在修改行为发生之后马上能看见此对象的新状态,如图1所示。

Read more

软件事务内存导论(十)处理写偏斜异常

声明:本文是《Java虚拟机并发编程》的第六章,感谢华章出版社授权并发编程网站发布此文,禁止以任何形式转载此文。

处理写偏斜异常

在6.6节中,我们曾经简单讨论了写偏斜(write skew)以及Clojure STM是如何解决这个问题的。Akka同样提供了处理写偏斜问题的支持,但是需要我们配置一下才能生效。OK,一听到配置这个词可能让你觉得有些提心吊胆,但实际操作起来其实起来还是蛮简单的。下面就让我们首先了解一下Akka在不进行任何配置情况下的默认行为。

Read more

软件事务内存导论(九) 集合与事务

声明:本文是《Java虚拟机并发编程》的第六章,感谢华章出版社授权并发编程网站发布此文,禁止以任何形式转载此文。

集合与事务

在我们努力学习这些示例的过程中,很容易就会忘记我们所要处理的值都必须是不可变的。只有实体才是可变的,而状态值则是不可变的。虽然STM已经为我们减轻了很多负担,但如果想要在维护不可变性的同时还要兼顾性能的话,对我们来说也将是一个非常严峻的挑战。

为了保证不可变性,我们采取的第一个步骤是将单纯用来保存数据的类(value classes)及其内部所有成员字段都置为final(在Scala中是val)。然后,我们需要传递地保证我们自己定义的类里面的字段所使用的类也都是不可变的。可以说,将字段和类的定义置为final这一步是整个过程的基础,这同时也是避免并发问题的第一步。

虽说不可变性可以使代码变得又好又安全,但是由于性能问题,程序员们还是不大愿意使用这一特性。其症结在于,为了维护不可变性,我们可能在数据没发生任何变动的情况下也要进行拷贝操作,而这种无谓的拷贝对性能伤害很大。为了解决这个问题,我们在3.6节中曾经讨论过持久化数据结构以及如何使用这类数据结构来减轻程序在性能方面的负担。而在持久化数据结构的实现方面,已经有很多现成的第三方库可供使用,而Scala本身也提供了这类数据结构。由于Java也有实现好的持久化数据结构可用,所以我们就无需专门为使用这个特性而去换用自己不熟悉的语言。

除了不可变性之外,我们还希望能获得一些事务运行所需要的数据结构——这些数据结构的值是不可变的,但其实体可以在托管事务中被改变。Akka提供了两种托管数据结构——TransactionalVector和TransactionalMap。这两种数据结构源自于高效的Scala数据结构,其工作原理和Java的list、map类似。下面就让我们一起来学习如何在Java和Scala中使用TransactionalMap

Read more

软件事务内存导论(八)提交和回滚事件

声明:本文是《Java虚拟机并发编程》的第六章,感谢华章出版社授权并发编程网站发布此文,禁止以任何形式转载此文。

提交和回滚事件

Java的try-catch-finally语法结构不但使我们可以安全地处理异常,还能够在程序抛出异常时选择性地执行一些代码。同样地,我们也可以控制程序在事务成功提交之后去执行某段代码,而当事务回滚时则去执行另一段代码。StmUtils中的deferred()和compensatiing()这两个函数分别提供了上述功能。特别地,在实现事务的过程中,为保证事务能顺利完成,我们通常会加入一些带副作用的逻辑,而deferred()函数则是一个执行所有这部分逻辑的绝佳地点。

Read more

Java 7 Concurrency Cookbook – Javier Fernández González -前言

原文下载链接      作者: Javier Fernández González     译者:郑玉婷

前言

当你用计算机工作的时候,你在同时做多样事情。你可以边听音乐边写文档边读取邮件。你可以这样做的原因是你的操作系统运行并发任务。并发编程是关于基础与进程的一个 提供多任务或者程序同时运行还相互沟通来交换数据和相互同步的平台。Java是一个并发平台,在Java程序中提供很多执行并发任务的类。每个版本,Java提升了促进程序员开发并发程序的功能。这本书包含了在Java版本7的并发API中最重要和最有用的技巧,所以你可以直接在你的应用程序中使用的,以下这些:

• 基本线程管理
• 线程同步机制
• 执行者代表的线程的创建与管理
• Fork/Join框架来提高应用程序的性能
• 并发程序的数据结构
• 按照需要来调整一些并发类的默认行为
• 测试Java的并发应用程序

Read more

软件事务内存导论(七)阻塞事务

声明:本文是《Java虚拟机并发编程》的第六章,感谢华章出版社授权并发编程网站发布此文,禁止以任何形式转载此文。

阻塞事务——有意识地等待

我们经常会遇到这样一种情况,即某事务T能否成功完成依赖于某个变量是否发生了变化,并且由于这种原因所引起的事务运行失败也可能只是暂时性的。作为对这种暂时性失败的响应,我们可能会返回一个错误码并告诉事务T等待一段时间之后再重试。然而在事务T等待期间,即使其他任务已经更改了事务T所依赖的数据,事务T也没法立即感知到并重试了。为了解决这一问题,Akka为我们提供了一个简单的工具——retry(),该函数可以先将事务进行回滚,并将事务置为阻塞状态直到该事物所依赖的引用对象发生变化或事务阻塞的时间超过了之前配置的阻塞超时为止。我本人更愿意将这一过程称为“有意识地等待”,因为这种说法听起来比“阻塞”更合适一些。下面让我们将阻塞(或有意识地等待)用于下面的两个例子当中。

Read more

非阻塞同步算法实战(一)

感谢trytocache投递本文。

前言

本文写给对ConcurrentLinkedQueue的实现和非阻塞同步算法的实现原理有一定了解,但缺少实践经验的朋友,文中包括了实战中的尝试、所走的弯路,经验和教训。

背景介绍

上个月,我被安排独自负责一个聊天系统的服务端,因为一些原因,我没使用现成的开源框架,网络那块直接使用AIO,收数据时,因为只会从channel里过来,所以不需要考虑同步问题;但是发送数据时,因为有聊天消息的转发,所以必需处理这个同步问题。AIO中,是处理完一个注册的操作后,再执行我们定义的方法,此时,如果还有数据需要写,则继续注册写操作,如果没有则不注册;提交数据时,如果当前没有注册写操作,则注册一个,否则仅提交(此时再注册则会报异常)。这样,需要同步的点就是:如何知道当前还有没有数据需要发送(因为其它线程也可以提交数据到此处),和如何知道此次提交时,有没有注册写操作。总之,要完成:有数据要发送时,必需有写操作被注册,并且只能注册一次;没有数据时,不能有写操作被注册。 Read more

Java并发中正确使用volatile

作者:一粟   整理和翻译自Twitter实时搜索的PPT

前几天并发编程群里有同学对volatile的用法提出了疑问,刚好我记得Twitter有关实时搜索的这个PPT对这个问题解释的很清晰并有一个实际的应用场景,于是周末把这个问题摘录了一些和并发相关的内容如下: Read more

软件事务内存导论(六)配置Akka事务

声明:本文是《Java虚拟机并发编程》的第六章,感谢华章出版社授权并发编程网站发布此文,禁止以任何形式转载此文。

配置Akka事务

默认情况下,Akka为其相关的运行参数都设定了默认值,我们可以通过代码或配置文件akka.conf来更改这些默认设置。如果想了解如何指定或修改该配置文件位置的详细信息,请参阅Akka的文档。

针对单个事务,我们可以利用TransactionFactory在程序代码中更改其设置。下面就让我们用这种方式先后在Java和Scala中更改一些设置来为你展示如何实现设置的变更。

Read more

return top