并发译文 ’ 目录归档

非一致性内存访问的读写锁

原文地址译文地址,译者: 李杰聪,校对:郑旭东

原文作者:

  • Irina Calciu         Brown University        irina@cs.brown.edu
  • Dave Dice          Oracle Labs             dave.dice@oracle.com
  • Yossi Lev           Oracle Labs             yossi.lev@oracle.com
  • Victor Luchangco    Oracle Labs              victor.luchangco@oracle.com
  • Virendra J. Marathe   Oracle Labs             virendra.marathe@oracle.com
  • Nir Shavit           MIT                   shanir@csail.mit.edu

摘要

因为多核和多芯片计算机的快速增长,非一致性内存访问(NUMA)架构在主流计算机系统中的地位越来越重要。为了在这些新系统上获取最好的性能,我们需要重新修改当前程序组成部分的并发算法和同步原语。这篇论文重新设计了很关键的同步原语——读写锁。

据我们所知,本文论述的读写锁是第一个专门为NUMA架构设计的,以及这个读写锁的变种。这些变种考虑了在高并发读的情况下的读和写的公平性以及在同一个NUMA节点上让写批量运行。我们的算法利用群组所技术来处理写者之间的同步,比较适合NUMA架构,同时使用二进制标志来协调读者和写者,利用简化的读者计数器,可以在NUMA上使读者间取得更好的并发性。最经过我们的基准程序测试之后,这些简单的NUMA锁算法竟然比目前比较出色的读-写锁的效率还高出10倍以上。为了了评估在真实环境中我们算法的效率,我们也提供了用基准程序 kccachetest测试的结果。Kccachetest属于Kyoto-Cabinet 发行版,这是一个开源的数据库使用了大量的 pthread 线程库的读写锁。跟最好的锁比,我们的锁也把kccachetest的效率提升了40%。 阅读全文

Storm入门之第三章拓扑

本文翻译自《Getting Started With Storm》  译者:吴京润   编辑:方腾飞

在这一章,你将学到如何在同一个Storm拓扑结构内的不同组件之间传递元组,以及如何向一个运行中的Storm集群发布一个拓扑。

数据流组

设计一个拓扑时,你要做的最重要的事情之一就是定义如何在各组件之间交换数据(数据流是如何被bolts消费的)。一个数据流组指定了每个bolt会消费哪些数据流,以及如何消费它们。

NOTE:一个节点能够发布一个以上的数据流,一个数据流组允许我们选择接收哪个。

数据流组在定义拓扑时设置,就像我们在第二章看到的:

···
    builder.setBolt("word-normalizer", new WordNormalizer())
           .shuffleGrouping("word-reader");
···

在前面的代码块里,一个boltTopologyBuilder对象设定, 然后使用随机数据流组指定数据源。数据流组通常将数据源组件的ID作为参数,取决于数据流组的类型不同还有其它可选参数。

NOTE:每个InputDeclarer可以有一个以上的数据源,而且每个数据源可以分到不同的组。
阅读全文

JSR133中文版

原文链接  译文链接   翻译:丁一   下载:JSR133中文版 firefox_old_school_final

本文是JSR-133规范,即JavaTM内存模型与线程规范,由JSR-133专家组开发。本规范是JSR-176(定义了JavaTM平台 Tiger(5.0)发布版的主要特性)的一部分。本规范的标准内容将合并到JavaTM语言规范JavaTM虚拟机规范以及java.lang包的类说明中。本JSR-133规范将不再通过JCP维护和修改。未来所有对这些标准化内容的更新、修正以及说明都会出现在上述这些文档中。

本规范的标准化内容包含在第5, 7, 9.2, 9.3, 11, 12, 14, 15以及16节。其它章节,以及上述提到的章节的部分内容,属非标准化内容,用于解释和说明标准化内容。如果标准化内容和非标准化内容有冲突,以标准化内容为准。

本规范的讨论与开发异常复杂且专业性强,需要对一些学术论题有深刻的见解并了解它们的发展过程。这些讨论在JMM web站点上都有存档。该站点提供了额外的信息,可以帮助理解本规范形成的过程。
阅读全文

上下文切换详解

原文地址译文地址,译者: 董明鑫,校对:郑旭东

上下文切换(有时也称做进程切换或任务切换)是指 CPU 从一个进程或线程切换到另一个进程或线程。
进程(有时候也称做任务)是指一个程序运行的实例。在 Linux 系统中,线程就是能并行运行并且与他们的父进程(创建他们的进程)共享同一地址空间(一段内存区域)和其他资源的轻量级的进程。
上下文是指某一时间点 CPU 寄存器和程序计数器的内容。寄存器是 CPU 内部的数量较少但是速度很快的内存(与之对应的是 CPU 外部相对较慢的 RAM 主内存)。寄存器通过对常用值(通常是运算的中间值)的快速访问来提高计算机程序运行的速度。程序计数器是一个专用的寄存器,用于表明指令序列中 CPU 正在执行的位置,存的值为正在执行的指令的位置或者下一个将要被执行的指令的位置,具体依赖于特定的系统。
稍微详细描述一下,上下文切换可以认为是内核(操作系统的核心)在 CPU 上对于进程(包括线程)进行以下的活动:(1)挂起一个进程,将这个进程在 CPU 中的状态(上下文)存储于内存中的某处,(2)在内存中检索下一个进程的上下文并将其在 CPU 的寄存器中恢复,(3)跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程。 阅读全文

Storm入门 第二章准备开始

本文翻译自《Getting Started With Storm》  译者:吴京润   编辑:方腾飞

准备开始

在本章,我们要创建一个Storm工程和我们的第一个Storm拓扑结构。

NOTE: 下面假设你的JRE版本在1.6以上。我们推荐Oracle提供的JRE。你可以到http://www.java .com/downloads/下载。

操作模式

开始之前,有必要了解一下Storm的操作模式。有下面两种方式。

本地模式

在本地模式下,Storm拓扑结构运行在本地计算机的单一JVM进程上。这个模式用于开发、测试以及调试,因为这是观察所有组件如何协同工作的最简单方法。在这种模式下,我们可以调整参数,观察我们的拓扑结构如何在不同的Storm配置环境下运行。要在本地模式下运行,我们要下载Storm开发依赖,以便用来开发并测试我们的拓扑结构。我们创建了第一个Storm工程以后,很快就会明白如何使用本地模式了。

阅读全文

一个通用并发对象池的实现

原文链接译文链接,原文作者: Sarma Swaranga,本文最早发表于deepinmind,校对:郑旭东

这篇文章里我们主要讨论下如何在Java里实现一个对象池。最近几年,Java虚拟机的性能在各方面都得到了极大的提升,因此对大多数对象而言,已经没有必要通过对象池来提高性能了。根本的原因是,创建一个新的对象的开销已经不像过去那样昂贵了。

阅读全文

Storm入门之第一章

storm
原书下载地址 译者:吴京润   编辑:方腾飞

译者注:本文翻译自《Getting Started With Storm》,本书中所有Storm相关术语都用斜体英文表示。 这些术语的字面意义翻译如下,由于这个工具的名字叫Storm,这些术语一律按照气象名词解释

  • spout 龙卷,读取原始数据为bolt提供数据
  • bolt 雷电,从spout或其它bolt接收数据,并处理数据,处理结果可作为其它bolt的数据源或最终结果
  • nimbus 雨云,主节点的守护进程,负责为工作节点分发任务。

下面的术语跟气象就没有关系了

  • topology 拓扑结构,Storm的一个任务单元
  • define field(s) 定义域,由spoutbolt提供,被bolt接收

本文是该书的第一章。

基础知识

Storm是一个分布式的,可靠的,容错的数据流处理系统。它会把工作任务委托给不同类型的组件,每个组件负责处理一项简单特定的任务。Storm集群的输入流由一个被称作spout的组件管理,spout把数据传递给bolt, bolt要么把数据保存到某种存储器,要么把数据传递给其它的bolt。你可以想象一下,一个Storm集群就是在一连串的bolt之间转换spout传过来的数据。 阅读全文

无锁并不像人们所说的那么好

原文链接译文连接,译者:梁海舰,校对:李任

注意,我将在这篇文章中说一些关于“无锁”和“无等待”算法的坏话。在我们开始之前,让我来问你一个问题:

你之前有过需要无锁算法来解决问题吗?为什么必须使用无锁算法来解决?
阅读全文

并发不是并行,它更好!

原文链接译文链接,译者:雷哥,饶命,校对:李任

现代社会是并行的:多核、网络、云计算、用户负载,并发技术对此有用。

Go语言支持并发,它提供了:并发执行(goroutines),同步和消息(channels)和多路并发控制(select)。
当Go声称是并发时,人们说:“并发很酷!耶,我可以并行运行了!”,但这是个错误的。因为很多人都不了解他们间的差别。“我用四个处理器来做质数筛选,但是更慢了。”

并发(Concurrency):以可独立执行的进程集合的方式编程(进程是出了名的难定义,这里是通常意义上的进程,不是Linux进程)

并行(Parallelism):以可同时执行的(可能相关的)计算指令方式编程。

两者的区别:并发是同时处理(dealing)很多的事情,并行是同时做(doing)很多的事情。不同,但也相关。一个是关于代码结构,一个是关于代码执行。并发为可能的(不是必须的)并行问题提供了一种解决方案。
阅读全文

为什么无等待如此重要

原文地址 ,译文链接,译者:张军,校对:梁海舰

无锁(完全同步)

想象一下,一个无锁算法或数据结构有一个方法,这个方法所有执行过程都需要同步。假设在单线程模式下这个方法每次调用需要10ns,而每增加一个线程调用这个方法,将在同步状态(变量)上产生争用。
很显然,如果只有一个线程,每次调用该方法到返回平均时间都为10ns,我们称之为:每10ns完成的任务数;如果你增加更多的线程,他们将会增加其他线程执行完成的时间,这是因为同一时刻只有一个线程能获得锁;
记住,无锁(Lock-Free)保证一个线程可以执行,但没说是哪一个,并且在当前这个特定的例子中,每次只有一个线程可以执行(完成任务),其他线程不得不从头开始:
阅读全文

Oracle官方并发教程之活跃度

原文地址译文地址,译者:李任,郑旭东 校对:蘑菇街-小宝

一个并发应用程序能及时执行的能力称为活跃性。本节将介绍最常见的活跃性问题:死锁(deadlock),以及另外两个活跃性问题:饥饿(starvation)和活锁(livelock)。

阅读全文

《Java 7并发编程实战手册》第五章Fork/Join框架

感谢人民邮电大学授权并发网发布此书样章,新书已上市,购买请进当当网Snip20140120_1

本章内容包含:

  • 创建Fork/Join线程池
  • 合并任务的结果
  • 异步运行任务
  • 在任务中抛出异常
  • 取消任务

5.1 简介

通常,使用Java来开发一个简单的并发应用程序时,会创建一些Runnable对象,然后创建对应的Thread 对象来控制程序中这些线程的创建、执行以及线程的状态。自从Java 5开始引入了ExecutorExecutorService接口以及实现这两个接口的类(比如ThreadPoolExecutor)之后,使得Java在并发支持上得到了进一步的提升。 阅读全文

无锁和无等待的定义和例子

原文链接译文连接,译者:周可人,校对:梁海舰

在查阅google之后,我发现没有一处对并发算法或是数据结构规定的演进条件(progress condition,注:参考[1],译者认为翻译为演进状态更为合适)做合理的解释。甚至在”The Art of Multiprocessor Programming“中也只有围绕书本的一小段定义,大部分定义是单行的句子,因而造成了我们普通人含义模糊的理解,所以在这里我把我对这些概念的理解整理在一起,并且在每一种概念后面给出相应的例子。

我们先将演进条件分为四个主要类别,阻塞(blocking),无干扰(obstruction-free),无锁(lock-free),和无等待(wait-free)。详细列表如下:
阅读全文

无等待是不够的

原文地址译文链接,译者:许巧辉,校对:周可人

无等待是不够的

以目前针对演进条件(progress condition,注:参考[1])的算法和数据结构的分类来看,是不足以区分不同演进条件的能力和每一个演进条件的性能/延迟。

我们提出了一种新的“大O”记号来表示无等待的算法和数据结构。下面是它的工作原理:

一个算法或功能被称为“Wait-Free O(x)“,表示需要最多O(x)操作完成。

阅读全文

Oracle官方并发教程之线程对象

原文链接译文链接,译者:郑旭东

在Java中,每个线程都是Thread类的实例。并发应用中一般有两种不同的线程创建策略。

  • 直接控制线程的创建和管理,每当应用程序需要执行一个异步任务的时候就为其创建一个线程
  • 将线程的管理从应用程序中抽象出来作为执行器,应用程序将任务传递给执行器,有执行器负责执行。

这一节,我们将讨论Thread对象,有关Executors将在高级并发对象一节中讨论。

阅读全文

return top