分享

JUC并发包、volatile、CAS、ConcurrentHashMap及各类锁一网打尽

 印度阿三17 2019-08-25

  之前学过比较长一段时间的JUC相关的知识,现在想复习一遍,因此在这里做一个简单的笔记。
  本篇博文都是比较基础的概念,而且比较简要,大家如果要深入理解,尽量多看一些高并发相关的书籍,如果才刚接触这一块的同学,建议学习《java并发编程从入门到精通》,这一本书入门还是很不错的!

一、volatile


1.什么是volatile

volatile是java虚拟机提供的轻量级的同步机制;

它具有三大特性:
保证可见性;
不保证原子性;
禁止指令重排(有序性)

2.JMM-java内存模型特性

可见性、原子性、有序性

3.volatile不保证原子性的问题怎么解决

使用java.util.concurrent.atomic类
AtomicInteger a = new AtomicInteger();

Atomic是怎么实现的呢?
主要是用到了CAS

4.CAS

全称Compare-and-swap,它是一条CPU并发原语,它的核心类是Unsafe类,可以直接操作内存。(开挂的人生不需要解释…)

CAS实现了原子性,怎么实现的呢?
CAS原理:CAS有三个操作数:内存中V,旧的预期值A,要修改的更新值B;
当且仅当就的预期值A和内存值V相同时,将内存值V修改为B。

CAS缺点:ABA问题;
有T1和T2两个线程,T1改一次10s,T2改一次2s,T2先把主内存中的A改成B,后面又将B改回为A,这时候轮到T1,发现主内存中的值为自己的期望值,就直接进行修改。这样首位是一样的,但中间已经被修改过多次了,而T1以为是操作成功的。这样有可能导致过程存在问题。简单理解就是狸猫换太子。

如何规避ABA问题?
使用原子引用更新AtomicStampedReference

二、集合线程安全类

1.ArrayList

ArrayList线程不安全
为什么不安全,因为add()方法没有加synchronized
而Vector()是线程安全的,因为其add()方法加锁了

集合线程安全问题抛出的异常
并发争抢修改导致
java.util.ConcurrentModificationException

2.解决ArrayList线程不安全

使用Vector()
使用Collections.synchronizedList(new ArrayList<>());
使用写时复制CopyOnWriteArrayList();

3.写时复制CopyOnWriteArrayList();

使用了读写分离的思想;
写的时候先将容器复制一份,然后修改其中的元素,最后将引用指向这个新的容器。

4.HashMap与HashSet的联系

HashMap的Key是HashSet,而value是一个叫RPESENT的常量

5.HashMap线程不安全怎么办?

使用ConcurrentHashMap

了解ConcurrentHashMap吗?
是JUC包中最重要的类
java1.7的ConcurrentHashMap,使用分段锁技术,可以参考
https://www.cnblogs.com/ITtangtang/p/3948786.html
java1.8的ConcurrentHashMap摒弃了1.7的segment设计,而是在1.8HashMap的基础上实现了线程安全的版本,即也是采用数组 链表 红黑树的形式。
https://www.cnblogs.com/nullzx/p/8647220.html
https://my.oschina.net/pingpangkuangmo/blog/817973

三、锁

1.公平锁和非公平锁

公平锁:多个线程按照申请锁的顺序来获取锁。非公平锁就是不按顺序来,可以随意插队。
ReentrantLock默认非公平锁、synchronized也是非公平锁

2.可重入锁(递归锁)

简单理解:只要拿到一把钥匙,其中的内容都能获得锁;
举例来说,家大门的锁已经开了,其他厨房和厕所的锁也可以获得。就是在类中可以把两个方法理解为同一把锁。

ReentrantLock和synchronized都是非公平的可重入锁,主要是为了防止死锁

3.自旋锁

一种没有用到锁的方式,采用循环的方式去尝试获取锁。

4.读写锁-独占锁(写锁)/共享锁(读锁)

ReentrantLock和synchronized都是独占锁
ReentrantReadWriteLock的写锁是独占锁,读锁是共享锁,实现了ReadWriteLock接口

读写分别调用不同的方法
读调用writeLock().lock();与writeLock().unlock();
写调用readLock().lock();与readLock().unlock();

5. CountDownLatch/CyclicBarrier/Semaphore

三者都是JCU包中的类,一种同步方式
CountDownLatch计数器,类似倒数发送火箭,先完成的就进行等待,每完成一个计数器减一,直到减为0,也就是所有人完成后才开始下一步,是一种同步方式;

CyclicBarrier则与前者相反,类似集齐七龙珠召唤神龙,先完成的就进行等待,每完成一个计数器加一,直到加到期望值,也就是所有人完成后才开始下一步,也是一种同步方式;

Semapho信号灯(信号量):常用于多个线程争夺多个资源的情况,比如去网红店吃饭需要排队,后来的先在外面等待,里面每走一桌就进一桌人。

6. JUC加锁的方法:

synchronized,Lock,ReadWriteLock,Semapho

来源:https://www./content-4-408951.html

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多