Archive for the ‘ 本站原创 ’ Category

深入理解Java内存模型(四)——volatile

本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/java-memory-model-4

volatile的特性

当我们声明共享变量为volatile后,对这个变量的读/写将会很特别。理解volatile特性的一个好方法是:把对volatile变量的单个读/写,看成是使用同一个锁对这些单个读/写操作做了同步。下面我们通过具体的示例来说明,请看下面的示例代码:

class VolatileFeaturesExample {
    //使用volatile声明64位的long型变量
    volatile long vl = 0L;

    public void set(long l) {
        vl = l;   //单个volatile变量的写
    }

    public void getAndIncrement () {
        vl++;    //复合(多个)volatile变量的读/写
    }

    public long get() {
        return vl;   //单个volatile变量的读
    }
}

Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 深入理解Java内存模型(四)——volatile



深入理解java内存模型系列文章

深入理解java内存模型系列文章是本人在InfoQ发表的并发编程的连载文章。

  1. 深入理解java内存模型(一)——基础
  2. 深入理解java内存模型(二)——重排序
  3. 深入理解java内存模型(三)——顺序一致性
  4. 深入理解java内存模型(四)——volatile
  5. 深入理解java内存模型(五)——锁
  6. 深入理解java内存模型(六)——final
  7. 深入理解java内存模型(七)——总结

提纲

java线程之间的通信对程序员完全透明,内存可见性问题很容易困扰java程序员,本文试图揭开java内存模型神秘的面纱。本文大致分三部分:重排序与顺序一致性;三个同步原语(lock,volatile,final)的内存语义,重排序规则及在处理器中的实现;java内存模型的设计目标,及其与处理器内存模型和顺序一致性内存模型的关系。

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 深入理解java内存模型系列文章



深入理解Java内存模型(三)——顺序一致性

本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/java-memory-model-3

数据竞争与顺序一致性保证

当程序未正确同步时,就会存在数据竞争。java内存模型规范对数据竞争的定义如下:

  • 在一个线程中写一个变量,
  • 在另一个线程读同一个变量,
  • 而且写和读没有通过同步来排序。

当代码中包含数据竞争时,程序的执行往往产生违反直觉的结果(前一章的示例正是如此)。如果一个多线程程序能正确同步,这个程序将是一个没有数据竞争的程序。

JMM对正确同步的多线程程序的内存一致性做了如下保证:

  • 如果程序是正确同步的,程序的执行将具有顺序一致性(sequentially consistent)–即程序的执行结果与该程序在顺序一致性内存模型中的执行结果相同(马上我们将会看到,这对于程序员来说是一个极强的保证)。这里的同步是指广义上的同步,包括对常用同步原语(lock,volatile和final)的正确使用。 Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 深入理解Java内存模型(三)——顺序一致性



深入理解Java内存模型(二)——重排序

本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/java-memory-model-2

数据依赖性

如果两个操作访问同一个变量,且这两个操作中有一个为写操作,此时这两个操作之间就存在数据依赖性。数据依赖分下列三种类型:

名称 代码示例 说明
写后读 a = 1;b = a; 写一个变量之后,再读这个位置。
写后写 a = 1;a = 2; 写一个变量之后,再写这个变量。
读后写 a = b;b = 1; 读一个变量之后,再写这个变量。

上面三种情况,只要重排序两个操作的执行顺序,程序的执行结果将会被改变。

前面提到过,编译器和处理器可能会对操作做重排序。编译器和处理器在重排序时,会遵守数据依赖性,编译器和处理器不会改变存在数据依赖关系的两个操作的执行顺序。

注意,这里所说的数据依赖性仅针对单个处理器中执行的指令序列和单个线程中执行的操作,不同处理器之间和不同线程之间的数据依赖性不被编译器和处理器考虑。

Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 深入理解Java内存模型(二)——重排序



深入理解Java内存模型(一)——基础

本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/java-memory-model-1

并发编程模型的分类

在并发编程中,我们需要处理两个关键问题:线程之间如何通信及线程之间如何同步(这里的线程是指并发执行的活动实体)。通信是指线程之间以何种机制来交换信息。在命令式编程中,线程之间的通信机制有两种:共享内存和消息传递。
在共享内存的并发模型里,线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信。在消息传递的并发模型里,线程之间没有公共状态,线程之间必须通过明确的发送消息来显式进行通信。
同步是指程序用于控制不同线程之间操作发生相对顺序的机制。在共享内存并发模型里,同步是显式进行的。程序员必须显式指定某个方法或某段代码需要在线程之间互斥执行。在消息传递的并发模型里,由于消息的发送必须在消息的接收之前,因此同步是隐式进行的。
Java的并发采用的是共享内存模型,Java线程之间的通信总是隐式进行,整个通信过程对程序员完全透明。如果编写多线程程序的Java程序员不理解隐式进行的线程之间通信的工作机制,很可能会遇到各种奇怪的内存可见性问题。
Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 深入理解Java内存模型(一)——基础



聊聊并发(六)ConcurrentLinkedQueue的实现原理分析

本文是作者原创,首发于InfoQ:http://www.infoq.com/cn/articles/ConcurrentLinkedQueue

1.    引言

在并发编程中我们有时候需要使用线程安全的队列。如果我们要实现一个线程安全的队列有两种实现方式一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现,而非阻塞的实现方式则可以使用循环CAS的方式来实现,本文让我们一起来研究下Doug Lea是如何使用非阻塞的方式来实现线程安全队列ConcurrentLinkedQueue的,相信从大师身上我们能学到不少并发编程的技巧。
Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 聊聊并发(六)ConcurrentLinkedQueue的实现原理分析



聊聊并发(五)原子操作的实现原理

本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/atomic-operation

1    引言

原子(atom)本意是“不能被进一步分割的最小粒子”,而原子操作(atomic operation)意为”不可被中断的一个或一系列操作” 。在多处理器上实现原子操作就变得有点复杂。本文让我们一起来聊一聊在Inter处理器和Java里是如何实现原子操作的。

Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 聊聊并发(五)原子操作的实现原理



聊聊并发系列文章

聊聊并发系列文章是我在InfoQ发表的并发编程连载文章。

  1. 聊聊并发(一)深入分析Volatile的实现原理
  2. 聊聊并发(二)Java SE1.6中的Synchronized
  3. 聊聊并发(三)Java线程池的分析和使用
  4. 聊聊并发(四)深入分析ConcurrentHashMap
  5. 聊聊并发(五)原子操作的实现原理
  6. 聊聊并发(六)ConcurrentLinkedQueue的实现原理
  7. 聊聊并发(七)Java中的阻塞队列
  8. 聊聊并发(八)Fork/Join框架介绍
  9. 聊聊并发(九)Java中的CopyOnWrite容器
  10. 聊聊并发(十)生产者消费者模式

未完待续。。。

聊聊并发(四)深入分析ConcurrentHashMap

本文是作者原创,发表于InfoQ:http://www.infoq.com/cn/articles/ConcurrentHashMap

术语定义

术语 英文 解释
哈希算法 hash algorithm 是一种将任意内容的输入转换成相同长度输出的加密方式,其输出被称为哈希值。 
哈希表 hash table 根据设定的哈希函数H(key)和处理冲突方法将一组关键字映象到一个有限的地址区间上,并以关键字在地址区间中的象作为记录在表中的存储位置,这种表称为哈希表或散列,所得存储位置称为哈希地址或散列地址。

线程不安全的HashMap

因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。
Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 聊聊并发(四)深入分析ConcurrentHashMap



聊聊并发(三)Java线程池的分析和使用

作者:方腾飞 原文发表于infoQ:http://www.infoq.com/cn/articles/java-threadPool

1.    引言

合理利用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。但是要做到合理的利用线程池,必须对其原理了如指掌。

Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 聊聊并发(三)Java线程池的分析和使用



聊聊并发(二)Java SE1.6中的Synchronized

本文属作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/java-se-16-synchronized

1 引言

在多线程并发编程中Synchronized一直是元老级角色,很多人都会称呼它为重量级锁,但是随着Java SE1.6对Synchronized进行了各种优化之后,有些情况下它并不那么重了,本文详细介绍了Java SE1.6中为了减少获得锁和释放锁带来的性能消耗而引入的偏向锁和轻量级锁,以及锁的存储结构和升级过程。

Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 聊聊并发(二)Java SE1.6中的Synchronized



聊聊并发(一)深入分析Volatile的实现原理

本文属于作者原创,原文发表于InfoQ:http://www.infoq.com/cn/articles/ftf-java-volatile

引言

在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”。可见性的意思是当一个线程修改一个共享变量时,另外一个线程能读到这个修改的值。它在某些情况下比synchronized的开销更小,本文将深入分析在硬件层面上Inter处理器是如何实现Volatile的,通过深入分析能帮助我们正确的使用Volatile变量。

Read more

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 聊聊并发(一)深入分析Volatile的实现原理



return top