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

感谢trytocache投递本文。

前言

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

背景介绍

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

Java并发中正确使用volatile

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

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

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

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

配置Akka事务

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

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

阅读全文

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

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

双端队列是一种元素可以从两端插入或删除的数据结构[Knu73]。据说实现一种基于锁的允许在双端队列的两端进行并发操作的方法非常困难[Gro07]。本节将展示一种分割设计策略,能实现合理且简单的解决方案,请看下面的小节中的三种通用方法。

阅读全文

C1X 系列 : 多线程 (N1494)

感谢林永听投递本文。  校对:方腾飞

1. 关于 C1X 标准

C1X 是 C 语言的下一个标准,用于取代现有的 C99 标准。 C1X 是一个非正式名字,该标准仍在制订中,最新的工作草案是 N1494 ,发布于 2010 年 6 月。与 C99 相比, C1X 在语言和库上有显著的变化,本文重点分析 N1494 草案中的多线程部分。

2. 呼之欲出的多线程

不瞒你说, C99 标准里面的内存模型仍然是单线程的,即所有代码都运行在一个线程(进程)内。也许,你简直不敢相信这个是真的,因为说不定你每天都与多线程打交道, 使用 _beginthread , CreateThread 或 pthread_create 等不同平台的函数去创建线程。当你担心每个变量被编译器优化时,不得不加上 volatile 修饰符时,或者加上内存栅栏 (memory barrier) ,都印证了 C99 为单线程的内存模型。

32 位保护模式的出现,催生了多任务操作系统的诞生,随之而来的就是多线程环境。随着多核时代的到来,多线程环境成为程序开发不可逃避的问题。无锁编程,并行编程等已经成熟的技术在 C 社区里,常常给初学者遥不可及的感觉。在迫切需要多线程的时代,不同厂商和平台都纷纷开发了各自的多线程库,如 POSIX 的 pthreads 和 window 的 winThread 。软件工程师在特定的平台下,使用各自的线程库来开发多线程或并发程序,并非很难,但可移植却成了他们面临的问题。如 pthreads 在默认情况下,互斥锁是非递归的,要使用递归互斥锁,程序库必须支持一些扩展 feature ;而 window 下的锁默认情况下是递归的。 lock-wait-wakup 方式也不尽然相同,这对开发跨平台的多线程程序来说无异于雪上加霜。

放眼 C 语言的后来者,如 Java ,很早就支持了多线程,并且它的内存模型在不断地修改,以适应发挥多线程的优势。 Erlang 作为一种天生的并发编程语言,踏上编程语言的行列,成为并发编程的新星。同时,很多脚本语都内置地支持线程类或结构。 C/C++ 作为后来加入到多线程的行列,尽管已经太晚了,但对于 C 语言社区来说,这无疑是最令人兴奋的消息了。

阅读全文

软件事务内存导论(五)创建嵌套事务

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

1.1    创建嵌套事务

在之前的示例中,每个用到事务的方法都是各自在其内部单独创建事务,并且事务所涉及的变动也都是各自独立提交的。但如果我们想要将多个方法里的事务调整成一个统一的原子操作的时候,上述做法就无能为力了,所以我们需要使用嵌套事务来实现这一目标。

通过使用嵌套事务,所有被主控函数调用的那些函数所创建的事务都会默认被整合到主控函数的事务中。除此之外,Akka/Multiverse还提供了很多其他配置选项,如新隔离事务(new isolated transactions)等。总之,使用了嵌套事务之后,只有位于最外层的主控函数事务提交时,其内部所做的变更才会被提交。在具体使用时,为了保证所有嵌套事务能够作为一个整体成功完成,我们需要保证所有函数都必须在一个可配置的超时范围内做完。
阅读全文

为代码签名,供后人瞻仰或唾弃,你敢吗?

如何衡量代码质量的好坏,是否有一个标准,是否可以量化?

我认为答案是否定的。如果今年中央给各省下个死命令,要求年度GDP增长达到10%,我相信每个省一定都能完成任务。这几年,GDP增长都在8%以上,CPI增长不到4%,民族复兴完成了62%,这些都量化的,你是否满意?

回到开发的问题上来,有一些数字,比如bug的个数,reopen的次数能说明一定的问题,但不是全部。它只能描述系统的外在质量的一部分,这个外在质量可以由QA来保证。但是内部质量只能靠开发自己来保证,牺牲内部质量来保证功能和外在质量是不应该的。 阅读全文

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

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

在商用计算机中,多核系统已经越来越常见了,本章将描述如何设计能更好利用多核优势的软件。我们将介绍一些习语,或者叫“设计模式”,来帮助您权衡性能、可扩展性和响应时间。在上一章我们说过,您在编写并行软件时最重要的考虑是如何进行分割。正确的分割问题能够让解决办法简单、可扩展并且高性能,而不恰当的分割问题则会产生缓慢且复杂的解决方案。
阅读全文

软件事务内存导论(四)创建事务

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

创建事务

我们创建事务的目的是为了协调针对多个托管引用的变更。事务将会保证这些变更是原子的,也就是说,所有的托管引用要么全部被提交要么全部被丢弃,所以在事务之外我们将不会看到有任何局部变更(partial changes)出现。此外,我们也可以用创建事务的方式来解决对单个ref先读后写所引发的相关问题。

Akka是用Scala开发出来的,所以如果我们工作中用的是Scala的话,就可以直接幸福地享用Akka简洁明了的API了。对于那些日常工作中不能使用Scala开发的程序员,Akka同样也提供了一组方便的API,以帮助他们通过Java语言来使用该类库的功能。本节我们将会看到如何利用Akka在Java和Scala中创建事务。

首先我们需要选一个适合用事务来解决的例子。我们在第5章中重构的EnergySource类使用了显式的加锁和解锁操作(其最终版本详见5.7节),下面让就我们将这些显式的加锁/解锁操作换用Akka的事务API来实现。

阅读全文

软件事务内存导论(三)用Akka/Multiverse STM实现并发

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

用Akka/Multiverse STM实现并发

上面我们已经学习了如何在Clojure里使用STM,我猜你现在一定很好奇如何在Java代码中使用STM。而对于这一需求,我们有如下选择:

  • 直接在Java中使用Clojure STM。方法非常简单,我们只需将事务的代码封装在一个Callable接口的实现中就行了,详情请参见第7章。
  • 喜欢用注解(annotation)的开发者可能会更倾向于使用Multiverse的STM API.
  • 除了STM之外,如果我们计划使用角色(actor),那么还可以考虑选择Akka库。

Multiverse是由Peter Veentjer主持开发的一个基于Java的STM实现。通过这个库,我们可以在Java代码中使用注解来标识事务边界。我们既可以用@TransactionalMethod注解将单个的方法标记为事务性的,也可以用@TransactionalObject注解将一个类的所有方法都标记为事务性的。为了与其他JVM上的语言进行集成,Multiverse还提供了一组丰富的API来控制事物的开始和结束。

Akka是一个由Jonas Boner主持开发的一个基于Scala的解决方案,该方案可以用于包括Java在内的很多其他运行于JVM上的语言。Akka不但提供了STM和基于角色(actor)的并发方案,还提供了将二者混合使用的选项。此外,Akka使用Multiverse作为其STM的实现并提供了ACI(ACID的子集)特性。

Akka的性能非常棒,并且由于它既支持STM又支持基于角色(actor)的模型(详情请参见第8章),本章我们将会用它来实现演示Java STM的例子。

阅读全文

软件事务内存导论(二)软件事务内存

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

1.1    软件事务内存

将实体与状态分离的做法有助于STM(软件事务内存)解决与同步相关的两大主要问题:跨越内存栅栏和避免竞争条件。让我们先来看一下在Clojure上下文中的STM是什么样子,然后再在Java里面使用它。

通过将对内存的访问封装在事务(transactions)中,Clojure消除了内存同步过程中我们易犯的那些错误(见《Programming Clojure》[Hal09]和《The Joy of Clojure》[FH11])。Clojure会敏锐地观察和协调线程的所有活动。如果没有任何冲突——例如,每个线程都在存取不同账户——则整个过程中就不会涉及到任何锁,于是也就不会有延迟,并最终达到最大的并发度。当有两个线程试图访问相同数据时,事务管理器就会介入解决冲突,而我们的代码也就无需涉及任何显式加锁的操作。下面让我们一起研究一下这套系统是如何运作的。

在设计上,值(values)是不可变的,而实体(identities)也仅在Clojure的事务中是可变的。在Clojure中,压根就没有改变状态的方法,也没有任何相关的编程工具可用。而如果出现任何试图在事务之外改变实体的动作时,系统就会抛出illegalStateException异常。换句话说,一旦与事务进行了绑定,在没有冲突时,所有变更都是即时生效的;而一旦发生冲突,Clojure将会自动将事务回滚并重试。我们程序员的主要职责是保证事务中的代码都是幂等的——这是我们在函数式编程中避免副作用的常用手段,而这种手段在Clojure的编程模型中也同样适用。 阅读全文

软件事务内存导论(一)前言

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

请回忆一下你最近完成那个需要对共享可变变量进行同步的项目。在那个项目中,你肯定无法身心愉悦地享受出色地完成工作所带来的乐趣,而是会陷入无尽的质疑之中并抓狂地挨个确认是否在所有需要的地方都作了适当的同步。在过去所经历过的编程工作中,我已经遇到过好几次这样令人神经衰弱的情况了,而其中绝大部分原因都是由于我们在用Java编程的时候没有遵循正确原则和方法来处理共享可变状态。如果我们在某个该同步的地方忘了进行同步,那些不可预知的、潜在的灾难性的结果就将在不远处等待着我们。但是人无完人,遗忘是我们的天性。所以我们应该充分利用工具来弥补我们自身的不足,同时也可以让工具帮助我们实现我们充满创意的大脑所追求的那些伟大的目标,而不是让错误一次次地打击我们的信心。为了能够得到可控的行为和结果,我们需要再次把目光投向JDK。

在本章中,我们将会通过使用Clojure中十分流行的软件事务内存(STM)模型来学习如何线程安全地处理共享可变性(shared mutability)。在需要的时候,我们可能会在示例项目中混入Clojure的代码。但是我们并非强迫你也要使用Clojure,因为随着Multiverse和Akka这些优秀工具的出现,我们也可以在Java中直接使用STM了。在本章中,我们会先来看看STM在Clojure里是什么样子,然后再学习如何用Java和Scala对事务内存进行编程。这种编程模型非常适用于那些读多写少的程序——它简单易用并能提供可预测的结果。 阅读全文

并发编程网站推荐

并发编程网站

  1. Thread newsgroup(很多多线程相关的问题)
  2. preshing
  3. Doug Lea workstation (并发编程大师Doug lea的个人网站)
  4. Concurrency mail list  (Doug lea搞的邮件列表)
  5. oracle dave  (oracle 并发编程小组成员)
  6. lycog.com
  7. edu papers (很多并发编程相关的论文)
  8. oracle concurrency (oracle网站)
  9. mechanical-sympathy(需要翻墙,主要分享如何利用硬件的特性来实现高性能编程)
  10. Quora concurrency (quora问答网站的并发问题讨论)
  11. stackoverflow concurrency(stackoverflow问答网站的并发问题讨论)
  12. developerworks concurrency(并发编程专题文章)
  13. tumblr concurrency (涵盖多个语言的并发相关文章)
  14. JDK concurrent(官方jdk1.6 concurrent包API中文文档)
  15. trans-memory (研究内存事务的网站)

阅读全文

Linux内核的内存屏障

原文链接 作者:David HowellsPaul E. McKenney 译者:曹姚君 校对:丁一

内容:

  1. 抽象的内存访问模型
  2. 什么是内存屏障?
  3. 显式内核屏障
  4. 隐式内核内存屏障
  5. CPU之间的锁屏障效应
  6. 什么地方需要内存障碍?
  7. 内核的I/O屏障效应
  8. 假想的最小执行顺序模型
  9. CPU缓存的影响
  10. CPU能做到的
  11. 使用示例
  12. 引用

阅读全文

使用与运算符代替求余运算符的技巧

1.性能对比:

求余运算:a MOD b就相当与a-(a DIV b)*b 的运算。

与运算:就是一个指令的事 阅读全文

return top