- 浏览: 41758 次
- 性别:
- 来自: 成都
最新评论
文章列表
Java并发包同步工具之Phaser
- 博客分类:
- Java 线程
前言
Phaser是从JDK7开始提供的一个可重复使用的同步机制,它在功能上类似于CyclicBarrier和CountDownLatch,但它支持更灵活的使用场景。使用Phaser不仅能够替代CyclicBarrier和CountDownLatch,还能够做到它们做不到的功能。
通过前面的章节我们知道,CyclicBarrier用于一组线程相互等待到达公共的屏障,而CountDownLatch用于一个或一组线程等待另一个或另一组线程(其实也相当于有一个公共屏障),不同的是CyclicBarrier的屏障能够被重复使用,而CountDownLatch却不能重复利用,但是它们 ...
Striped64原理
通过前面的几章关于原子类的同步数据结构分析,我们知道Java并发包提供的原子类都是采用volatile+CAS机制实现的,这种轻量级的实现方式比传统的synchronize一般来说更加高效,但是在高并发下依然会导致CAS操作的大量竞争失败自旋重试,这时候对性能的影响说不定还不如使用synchronize,幸运的是,从JDK8开始Java并发包新增了抽象类Striped64以及它的扩展类 LongAdder、LongAccumulator、DoubleAdder、DoubleAccumulator解决了高并发下的累加问题。
我们知道普通的原子类例如At ...
引言
ThreadLocalRandom类是从JDK7开始在并发包下新增的随机数生成器,它解决了Random类在多线程下多个线程竞争内部唯一的原子性种子变量而导致大量线程自旋重试的不足。ThreadLocalRandom为后面要探讨的高并发累加器Striped64及其实 ...
引言
在上一文CPU高速缓存行之伪共享中,我们探讨了高速缓存行的伪共享对Java程序带来的问题以及坎坷的解决之路。幸运的是,最终由官方给出了sun.misc.Contended注解结束了这场悲剧。在上文中可以发现,对于Java对象的内存布局还是比较重要的,而且Contended注解不但能够用在类上,还能用在具体的字段上,而且还能进行分组,本文将详细了解该注解。当然在这之前,有必要对Java对象的内存布局等相关知识有一定的了解。
Java对象内存布局
对于Java对象的内存布局,其实在Java内存模型JMM之六深入理解synchronized(1)一文中已经有一个大概的了解,一个J ...
CPU高速缓存行之伪共享
- 博客分类:
- Java 线程
什么是伪共享
为了理解“伪共享”,在上一文CPU高速缓存那些事儿中我们主要对CPU高速缓存的原理构造进行大致的了解,其实通过CPU高速缓存的理解以及在文末提到的缓存一致性协议,我们已经能够很容易的理解所谓的“伪共享”的问题。
在这里,我们在来回顾一下CPU高速缓存的知识,在现代计算机中,CPU缓存是分层次结构的,例如:L1,L2,L3,当CPU发起一个读取内存指令的时候,首先在一级缓存L1中查找,如果不命中继续到低一层缓存中查找,缓存中没有直到最后到内存或硬盘上读取,读取到想要的内存地址之后,将由低一层的存储结构返回包含该内存地址的一个缓存行至上一层缓存,最上一层缓存获得该 ...
CPU高速缓存那些事儿
- 博客分类:
- Java 线程
引言
在分析JDK8新增的高并发原子累加器Striped64的时候,发现有一个“伪共享”的概念,而要理解它必须对CPU缓存有一定的了解,所以本文将先对CPU的缓存架构以及一些相关术语做一个研究探索。
CPU缓存的原理
众所 ...
同步数据结构之原子复合类
- 博客分类:
- Java 线程
引言
前面介绍的原子更新器都只是针对单个对象或者字段元素进行原子更新操作,在序章中提到的第四类复合型的原子更新器可以将一个引用变量与其他变量绑定到一起,实现复合的原子更新操作,这类更新器有两个: AtomicMa ...
同步数据结构之原子字段类
- 博客分类:
- Java 线程
引言
接下来是原子类序章中我们提到的原子更新字段类,它们是AtomicLongFieldUpdater,AtomicIntegerFieldUpdater,AtomicReferenceFieldUpdater。其实就是了原子的更新一个引用类型的整形字段、long型字段、引用类型字段。
AtomicIntegerFieldUpdater
首先根据如下的类结构可见,它本身是一个抽象方法,提供了一个静态工厂方法newUpdater()来生成实例。
public abstract class AtomicIntegerFieldUpdater<T> {
@Calle ...
同步数据结构之原子数组类
- 博客分类:
- Java 线程
引言
通过原子类序章我们知道Java并发包提供的原子类共分5类,这里开始介绍第二类数组类,其实也就是通过数组下标原子更新基本类型和引用类型的数组中的元素,它们是:AtomicIntegerArray,AtomicLongArray,AtomicReferenceArray。由于AtomicLongArray与AtomicIntegerArray非常类似,所以我还是重点对AtomicIntegerArray和AtomicReferenceArray进行分析。
AtomicIntegerArray
在分析其具体原子更新方法之前,我们有必要先了解一下AtomicIntegerArray ...
同步数据结构之原子标量类
- 博客分类:
- Java 线程
引言
通过原子类序章我们知道Java并发包提供的原子类共分5类,这里开始介绍第一类标量类,其实也就是原子更新基本类型和引用类型,它们是:AtomicBoolean,AtomicInteger,AtomicLong,AtomicReference. 它们提供的方法基本相同,其中AtomicBoolean最简单,其它三个提供的方法复杂度相当,这里我先以最常使用的AtomicInteger为例进行分析。
AtomicInteger
除了在序章中提到的方法之外,AtomicInteger主要由以下四类方法(我按照自己的理解取名划分的)构成对原子变量的更新操作。
1. 简单自更新
...
同步数据结构之原子类序章
- 博客分类:
- Java 线程
概述
关于Java并发包的原子相关类其实可以在Unsafe后面紧接着进行介绍,因为这些原子类其实只是建立在对Unsafe的调用基础上并没有利用到Java并发包的其他类,出于前面介绍的同步组件在Java并发包的重要性,我才将它们放在了原子类的前面。
Java从JDK 1.5开始提供的java.util.concurrent.atomic原子包给开发人员提供了一组用法简单、性能高效、线程安全的更新单个变量的方法。并且相对于使用传统的synchronized关键字的方式,原子包从使用者层面上看,是一种更加轻量级、细粒度、无锁的保证线程安全的策略。
因为原子包其实采用的是CAS + Volat ...
引言
在上一章我们了解了ReentrantReadWriteLock读写锁,它实现了多个读操作之间不再被相互等待阻塞,但是读操作和写操作之间,写操作和写操作之间依然还是会被相互阻塞。另外,ReentrantReadWriteLock读写锁有个很致命的缺陷,那 ...
关于Java按位取反“~”操作
- 博客分类:
- Java 基础
前言
在分析一些jdk8的源码比如StampedLock的时候,发现有对long类型的变量进行“~”操作:
private static final long RBITS = 127;
private static final long SBITS = ~RBITS;
上面的代码中,long型变量RBITS为127,通过对其进行“~”操作得到SBITS, ...
前言
在前面我们介绍的独占式同步组件ReentrantLock实现了标准的互斥操作,它是和synchronize关键字一样在某一时刻只有一个线程能够获得同步锁,从使用者的角度出发,它还是一种保守锁策略,试想:对共享资源的并发访问中,大部分都是执行读操作,而变更共享资源的写操作却非常少,在这种情况下,虽然读操作并不会影响共享数据的一致性,但是采用ReentrantLock独占锁的时候,多个执行读操作的线程依然需要互斥访问,这势必会大大降低吞吐量。如果能够做到只在执行写操作的时候进行互斥访问共享资源,对执行读操作的线程允许它们并行的访问共享资源,当然读操作必须要能够及时发现写操作对共享数据的修 ...