并发编程之J.U.C的第二篇

2020-02-25  本文已影响0人  小小一技术驿站

@TOC

3.2 StampedLock

该类自JDK8加入,是为了进一步优化读性能,它的特点是使用读锁、写锁时都必须配合【戳】使用
加解读锁


在这里插入图片描述

加锁写锁


在这里插入图片描述
乐观锁,StampedLock 支持 tryOptimisticRead()方法(乐观读),读取完毕后需要做一次戳校验,如果校验通过,表示这期间确实没有写操作,数据可以安全使用,如果校验没通过,需要重新获取读锁,保证数据安全。
在这里插入图片描述

4. Semaphore

信号量,用来限制能同时访问共享资源的线程上限。


在这里插入图片描述

Semaphore原理

  1. 加锁解锁流程
    Semaphore 有点像一个停车场,permits 就好像停车位数量,当线程获得了 permits就像是获得了停车位,然后停车场显示空余车位减一
    刚开始,permits(state)为3,这时5个线程来获取资源


    在这里插入图片描述

    假设其中 Thread - 1,Thread - 2,Thread -4 cas 竞争成功,而Thread - 0和Thread - 3 竞争失败,进入AQS队列park阻塞


    在这里插入图片描述
    这时 Thread - 4 释放了 permits,状态如下
    在这里插入图片描述
    接下来Thread - 0 竞争成功,permits再次设置为0,设置自己为head节点,断开原来的head节点,unpark接下来的Thread - 3 节点,但由于 permits是0,因此Thread - 3 在尝试不成功后再次进入 park状态
    在这里插入图片描述

5. CountdownLatch

用来进行线程同步协作,等待所有线程完成倒计时。
其中构造参数用来初始化等待计数值,await()用来等待计数归零,countDown()用来让计数减一

6. CyclicBarrier

循环栅栏,用来进行线程协作,等待线程满足某个计数。构造时设置【计数个数】,每个线程执行到某个需要“同步”的时刻调用await()方法进行等待,当等待的线程数满足【计数个数】时,继续执行


在这里插入图片描述

7.线程安全集合类概述

在这里插入图片描述

线程安全集合类可以分为三大类 :

8. ConcurrentHashMap

单词计数问题 :

在这里插入图片描述
在这里插入图片描述
重要属性和内部类
在这里插入图片描述
构造器分析
可以看到实现了懒惰初始化,在构造方法中仅仅计算了table的大小,以后在第一次使用时才会真正的创建
在这里插入图片描述
get流程分析
在这里插入图片描述
put流程
以下数组简称(table),链表简称(bin)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
size计算流程
size计算实际发生在put、remove改变集合元素的操作之中

3. JDK7 ConcurrentHashMap

它维护了一个segment数组,每个segment对应一把锁

  1. 基本的入队出队


    在这里插入图片描述

    初始化链表 last = head = new Node<E>(null);Dummy节点用来占位,item为null


    在这里插入图片描述
    当一个节点入队 last = last.next = node;
    在这里插入图片描述

    再来一个节点入队 last = last.next = node


    在这里插入图片描述
    出队
    在这里插入图片描述
    h = head
    在这里插入图片描述
    first = h.next
    在这里插入图片描述
    h.next = h
    在这里插入图片描述

    head = first


    在这里插入图片描述
    E x = first.item;
    first.item = null;
    return x;
    在这里插入图片描述
  2. 加锁分析
    高明之处在于用了两把锁和dummy节点

3. 性能比较

主要列举 LinkedBlockingQueue与ArrayBlockingQueue的性能比较

10. ConcurrentLinkedQueue

ConcurrentLinkedQueue的设计与LinkedBlockingQueue 非常像,也是

11. CopyOnWriteArrayList

CopyOnWriteArraySet 是它的马甲
底层实现采用了写入时拷贝的思想,增删改操作会将底层数组拷贝一份,更改操作在新数组上执行,这时不影响其他线程的并发读、读写分离

在这里插入图片描述
这里的源码版本是Java11,在Java1.8中使用的是可重入锁而不是synchronized,其它读操作并未加锁,例如 :
在这里插入图片描述
适合【读多写少】的应用场景
get弱一致性
在这里插入图片描述
在这里插入图片描述
迭代器弱一致性
在这里插入图片描述
不要觉得弱一致性就不好
上一篇 下一篇

猜你喜欢

热点阅读