Archive for ‘ October, 2013

AbstractQueuedSynchronizer的介绍和原理分析

感谢同事【魏鹏】投递本稿。 Dedicate to Molly.

简介

提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架。该同步器(以下简称同步器)利用了一个int来表示状态,期望它能够成为实现大部分同步需求的基础。使用的方法是继承,子类通过继承同步器并需要实现它的方法来管理其状态,管理的方式就是通过类似acquire和release的方式来操纵状态。然而多线程环境中对状态的操纵必须确保原子性,因此子类对于状态的把握,需要使用这个同步器提供的以下三个方法对状态进行操作:

  • java.util.concurrent.locks.AbstractQueuedSynchronizer.getState()
  • java.util.concurrent.locks.AbstractQueuedSynchronizer.setState(int)
  • java.util.concurrent.locks.AbstractQueuedSynchronizer.compareAndSetState(int, int)

子类推荐被定义为自定义同步装置的内部类,同步器自身没有实现任何同步接口,它仅仅是定义了若干acquire之类的方法来供使用。该同步器即可以作为排他模式也可以作为共享模式,当它被定义为一个排他模式时,其他线程对其的获取就被阻止,而共享模式对于多个线程获取都可以成功。

Read more

《多核编程的艺术》读书笔记

感谢网友 郑思遥 投递本稿。

这份笔记是我2013年下半年以来读“The Art of Multiprocessor Programming”这本书的读书笔记。目前有关共享内存并发同步相关的书籍并不多,但是学术文献却不少,跨越的时间范围也非常长,说明人们一直在做出努力。

这本书是这个领域的好书,作为一本好书,它总结了这个领域自发展以来的大量重要成果,介绍了共享内存同步的基本理论,并介绍了大量并发算法和数据结构(主要是无锁算法),包括并发队列、栈、链表、计数器、排序网络、散列、跳表、优先队列等。

更为重要的是,本书的作者之一Maurice Herlihy就是并发同步领域的泰斗级人物,本身提出了无等待同步的基本理论,还提出了不少重要的无锁算法,因此这本书的权威性和重要性毋庸置疑。为了加深自己对重要概念的理解,同时受到Hawstein的“把《编程珠玑》读薄”这篇博文的启发和刘未鹏《暗时间》的影响,我决定用自己的语言把这本书的重要内容复述一遍,其中也加入了自己的一些想法和理解,希望这份笔记能对这本书的其他读者有帮助,也希望能对所有对共享内存同步的朋友们有帮助,这份笔记本身也能作为共享内存式同步的教程,但是笔记本身不能取代原书。 Read more

基于锁的并发算法 vs 无锁的并发算法

原文链接 作者:Martin Thompson  译者:曹姚君 校对: 方腾飞

上周在由Heinz Kabutz通过JCrete 组织的开放空间会议(unconference)上,我参加一个新的java规范 JSR166 StampedLock的审查会议。StampedLock 是为了解决多个readers 并发访问共享状态时,系统出现的内存地址竞争问题。在设计上通过使用乐观的读操作,StampedLock 比ReentrantReadWriteLock 更加高效;

在会议期间,我突然意思到两点:

  • 第一、我想是时候该去回顾java中锁的实现的现状。
  • 第二、虽然StampedLock 看上去是JDK很好的补充,但是它视乎忽略了一个事实,即在多个reader的场景里,无锁的算法通常是更好的解决方案。

Read more

WildFly评估之WildFly的模块化系统

Wildfly_logo

感谢朋友【吴杰】投递本文。

WildFly,前身是JBoss AS,从V8开始为区别于JBoss EAP,更名为WildFly。Wildfly 8主要具备如下特性:

  • Java EE7的参考实现(2013年7月止尚未得到Java EE7兼容认证)
  • 启动速度更快,占用内存更少
  • 模块化(JSR294)设计
  • 统一配置管理
  • 分布式domain管理

本文主要讨论一下WildFly 8的模块化系统。

WildFly之所以启动很快,模块化组件jboss-modules功不可没。作为OSGi和Jigsaw(JSR 294 http://jcp.org/en/jsr/detail?id=294)“夹击”之下的衍生物,与jboss-msc成为WildFly的全新内核。 Read more

JVM性能优化, Part 5:Java的伸缩性

感谢朋友【吴杰】投递本文。

JVM性能优化系列文章由Eva Andearsson在javaworld上发表共计5篇文章,ImportNew上有前4篇译文。本文(第5篇)由吴杰翻译自:javaworld 。

很多程序员在解决JVM性能问题的时候,花开了很多时间去调优应用程序级别的性能瓶颈,当你读完这本系列文章之后你会发现我可能更加系统地看待这类的问题。我说过JVM的自身技术限制了Java企业级应用的伸缩性。首先我们先列举一些主导因素。

  • 主流的硬件服务器提供了大量的内存
  • 分布式系统有大量内存的需求,而且该需求在持续增长
  • 一个普通Java应用程序所持有的对空间大概在1GB~4GB,这远远低于一个硬件服务器的内存管理能力以及一个分布式应用程序的内存需求量。这被称之为Java内存墙,如下图所示(图中表述Java应用服务器和常规Java应用的内存使用量的演变史)。

图 1 Java内存墙(1980~2010)

Java内存墙

Java内存墙

上图源自:Azul Systems Read more

JVM 内部运行线程介绍

感谢同事[觉梦]投递此稿。

hi,all

最近抽时间把JVM运行过程中产生的一些线程进行了整理,主要是围绕着我们系统jstack生成的文件为参照依据。  前段时间因为系统代码问题,造成性能瓶颈,于是就dump了一份stack出来进行分析。  stack 里面线程非常多,排查起来需要一定的经验,所以,对它们有一定了解,可以提高排查问题的效率。  现在网上资料也不是特别全,所以,导致很多新人在拿到一个stack文件之后,也不知知道从何看起。 下面我把这次整理的一些个人认为比较常见的线程列出来。 Read more

双重检查锁定与延迟初始化

本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/double-checked-locking-with-delay-initialization

双重检查锁定的由来

在java程序中,有时候可能需要推迟一些高开销的对象初始化操作,并且只有在使用这些对象时才进行初始化。此时程序员可能会采用延迟初始化。但要正确实现线程安全的延迟初始化需要一些技巧,否则很容易出现问题。比如,下面是非线程安全的延迟初始化对象的示例代码:

public class UnsafeLazyInitialization {
    private static Instance instance;

    public static Instance getInstance() {
        if (instance == null)          //1:A线程执行
            instance = new Instance(); //2:B线程执行
        return instance;
    }
}

在UnsafeLazyInitialization中,假设A线程执行代码1的同时,B线程执行代码2。此时,线程A可能会看到instance引用的对象还没有完成初始化(出现这种情况的原因见后文的“问题的根源”)。 Read more

测试并发应用(二)监控Phaser类

声明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 译者:郑玉婷

监控Phaser类

Java 并发 API 提供的其中一个最复杂且强大的功能是使用 Phaser 类来执行同步phased任务。当有些任务可以分成步骤执行时,此机制是很有用的。Phaser类提供的同步线程机制是在每个步骤的末端, 所以全部的线程都完成第一步后,才能开始执行第二步。

在这个指南,你将学习如何从Phaser类获取其状态信息。
Read more

测试并发应用 (一)监控Lock接口

声明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 译者:郑玉婷  

校对:方腾飞

监控Lock接口

Lock 接口是Java 并发 API提供的最基本的机制来同步代码块。它允许定义临界区。临界区是代码块可以共享资源,但是不能被多个线程同时执行。此机制是通过Lock 接口和 ReentrantLock 类实现的。

在这个指南,你将学习从Lock对象可以获取的信息和如何获取这些信息。 Read more

C++11 并发编程指南——前言

开场白:前一段时间(大概在8月初)开始写 《C++11 并发编程指南》(最早更新于:http://www.cnblogs.com/haippy),但是由于个人能力有限,加上 9 月初到现在一直在忙着找工作(革命尚未成功),精力有限,难免出现错误,希望读者不吝指正。

另外,这是我在并发编程网上写的第一篇文章,终于迈开了第一步。受@腾飞同学的鼓励,后续我会在本站持续更新与 C++ 并发编程(尤其是C++11并发编程)相关的文章,但由于个人水平有限,希望读者指出我的错误,并多多包涵 😉

最后,个人一直在 Github上 更新 《C++11 并发编程指南》,目前已经完成了 C++11 新标准中与原子操作和多线程相关的内容,如果你对此感兴趣,也欢迎你加入进来,传播知识,方便他人。 Read more

第八章- 测试并发应用(引言)

声明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 译者:郑玉婷

8
测试并发应用

章节提要:

  • 监控Lock接口
  • 监控Phaser类
  • 监控执行者框架
  • 监控Fork/Join池
  • 编写有效的日志
  • FindBugs分析并发代码
  • 配置Eclipse来调试并发代码
  • 配置NetBeans来调试并发代码
  • MultithreadedTC测试并发代码

Read more

线程同步工具(六)控制并发阶段性任务的改变

声明:本文是《 Java 7 Concurrency Cookbook 》的第三章, 作者: Javier Fernández González 译者:郑玉婷

控制并发阶段性任务的改变

Phaser 类提供每次phaser改变阶段都会执行的方法。它是 onAdvance() 方法。它接收2个参数:当前阶段数和注册的参与者数;它返回 Boolean 值,如果phaser继续它的执行,则为 false;否则为真,即phaser结束运行并进入 termination 状态。

如果注册参与者为0,此方法的默认的实现值为真,要不然就是false。如果你扩展Phaser类并覆盖此方法,那么你可以修改它的行为。通常,当你要从一个phase到另一个,来执行一些行动时,你会对这么做感兴趣的。

在这个指南,你将学习如何控制phaser的 phase的改变,通过实现自定义版本的 Phaser类并覆盖 onAdvance() 方法来执行一些每个phase 都会改变的行动。你将要实现一个模拟测验,有些学生要完成他们的练习。全部的学生都必须完成同一个练习才能继续下一个练习。 Read more

线程同步工具(七)在并发任务间交换数据

声明:本文是《 Java 7 Concurrency Cookbook 》的第三章, 作者: Javier Fernández González 译者:郑玉婷

在并发任务间交换数据

Java 并发 API 提供了一种允许2个并发任务间相互交换数据的同步应用。更具体的说,Exchanger 类允许在2个线程间定义同步点,当2个线程到达这个点,他们相互交换数据类型,使用第一个线程的数据类型变成第二个的,然后第二个线程的数据类型变成第一个的。

这个类在遇到类似生产者和消费者问题时,是非常有用的。来一个非常经典的并发问题:你有相同的数据buffer,一个或多个数据生产者,和一个或多个数据消费者。只是Exchange类只能同步2个线程,所以你只能在你的生产者和消费者问题中只有一个生产者和一个消费者时使用这个类。

在这个指南,你将学习如何使用 Exchanger 类来解决只有一个生产者和一个消费者的生产者和消费者问题。 Read more

线程同步工具(五)运行阶段性并发任务

声明:本文是《 Java 7 Concurrency Cookbook 》的第三章, 作者: Javier Fernández González 译者:郑玉婷

运行阶段性并发任务

Java 并发 API 提供的一个非常复杂且强大的功能是,能够使用Phaser类运行阶段性的并发任务。当某些并发任务是分成多个步骤来执行时,那么此机制是非常有用的。Phaser类提供的机制是在每个步骤的结尾同步线程,所以除非全部线程完成第一个步骤,否则线程不能开始进行第二步。

相对于其他同步应用,我们必须初始化Phaser类与这次同步操作有关的任务数,我们可以通过增加或者减少来不断的改变这个数。

在这个指南,你将学习如果使用Phaser类来同步3个并发任务。这3个任务会在3个不同的文件夹和它们的子文件夹中搜索扩展名是.log并在24小时内修改过的文件。这个任务被分成3个步骤:

1. 在指定的文件夹和子文件夹中获得文件扩展名为.log的文件列表。
2. 过滤第一步的列表中修改超过24小时的文件。
3. 在操控台打印结果。

在步骤1和步骤2的结尾我们要检查列表是否为空。如果为空,那么线程直接结束运行并从phaser类中淘汰。 Read more

线程同步工具(四)在同一个点同步任务

声明:本文是《 Java 7 Concurrency Cookbook 》的第三章, 作者: Javier Fernández González 译者:郑玉婷

在同一个点同步任务

Java 并发 API 提供了可以允许2个或多个线程在在一个确定点的同步应用。它是 CyclicBarrier 类。此类与在此章节的等待多个并发事件完成指南中的 CountDownLatch 类相似,但是它有一些特殊性让它成为更强大的类。

CyclicBarrier 类有一个整数初始值,此值表示将在同一点同步的线程数量。当其中一个线程到达确定点,它会调用await() 方法来等待其他线程。当线程调用这个方法,CyclicBarrier阻塞线程进入休眠直到其他线程到达。当最后一个线程调用CyclicBarrier 类的await() 方法,它唤醒所有等待的线程并继续执行它们的任务。

CyclicBarrier 类有个有趣的优势是,你可以传递一个外加的 Runnable 对象作为初始参数,并且当全部线程都到达同一个点时,CyclicBarrier类 会把这个对象当做线程来执行。此特点让这个类在使用 divide 和 conquer 编程技术时,可以充分发挥任务的并行性,

在这个指南,你将学习如何使用 CyclicBarrier 类来让一组线程在一个确定点同步。你也将使用 Runnable 对象,它将会在全部线程都到达确定点后被执行。在这个例子里,你将在数字矩阵中查找一个数字。矩阵会被分成多个子集(使用divide 和 conquer 技术),所以每个线程会在一个子集中查找那个数字。一旦全部行程运行结束,会有一个最终任务来统一他们的结果。 Read more

return top