之前学过比较长一段时间的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
最后:
下一篇文章将继续讲相关知识,设计阻塞队列和线程池
最近一看,被自动设置为VIP文章了,感觉不方便大家学习,于因此取消掉了VIP观看。
觉得不错可以点赞或关注哟~