并发编程艺术-6
本文主要介绍的是java 并发容器和框架,主要包含了ConcurrentHashMap,ConcurrentLinkedQueue, java 中的阻塞队列和Fork/join 框架。
使用HashMap : 非线程安全,有可能导致死循环等。
使用HashTable: 使用synchronized,性能低下。
- CocurrentHashMap : 锁分段技术的使用,当一个线程占用锁访问其中的一个段数据的时候,其他段也能被其他线程访问。
下图是一张简易的结构图,其中segment是数组结构,每一个segment 里面是一个entry 数组,然后每一个entry 是链表结构,对于entry 数组中的数组数据进行修改的时候,就要进行先获取到他对应的Segment 锁。
- ConcurrentLinkedQueue:采用非阻塞的实现方式,即使用循环CAS方式实现。
入队过程: 定位出尾节点,然后使用CAS将入队节点设置成尾节点的next 节点,不成功则重试。
出队过程:首先获取头结点,判断头结点元素是否为空,如果为空,表示已经有另外一个线程获取了,如果不为空,则使用CAS将头结点设置成null,CAS成功,则直接返回头结点元素,如果不成功,说明另外有线程出队更新了头结点,导致元素变化。
- java 中的阻塞队列:
(1) 阻塞插入:当队列满的时候,队列会阻塞插入元素的线程,直到队列不阻塞(有界队列)
(2) 阻塞移除:在队列为空的时候,获取元素的线程会等待队列变为非空。
下面是阻塞队列的7个实现:
ArrayBlockingQueue: 数组构成,有界
LinkedBlockingQueue 链表构成, 有界
PriorityBlockingQueue 支持优先级,无界
DelayQueue 支持优先级, 无界
SychronousQueue 不存储元素,负责把生产者的数据直接传递给消费者
LinkedTransferQueue 链表构成,无界
LinkedBlockingDeque 链表构成,双向
阻塞队列的实现原理 :
使用通知者模式实现。
- Fork/join
ForkJoinPool 由ForkJoinTask数组和ForkJoinWorkerThread 数组组成,前者负责将存放程序提交给ForkJoinPool 的任务,后者负责执行这些任务。