对JUC并发包常用工具的理解
1、CAS(compare and swap)
比较并交换,他操纵3个值,期望值,内存值,新值,当且仅当内存值等于期望值的时候,才将内存值改为新值;如果内存值和期望值不相等,说明有其他线程修改了内存值,那么他的此次操作就作废。底层通过unsafe去实现(直接操作类、内存、实例),cpu的原语操作.属于乐观锁
乐观锁,就是凡事都往好的地方想,认为别的线程不会去修改自己需要的数据,所以他占有资源时,并不会加锁,只是修改完数据再去比较数据有没有被其他线程修改。
悲观锁,凡是都往坏的地方想,认为总有人想动自己的数据,所以他会第一时间去加锁,让自己独享资源。
2、reentrantLock
可以替代synchronized,但是他可以通过lock()/unlock()获取锁、释放锁,synchronized是系统自动加锁、自动解锁;他是API级别的锁,而synchronized是JVM级别的锁,可以通过lockInterrupibly()可以被打断的加锁,对interrupt()做出响应,可以使用tryLock尝试在指定时间内获取锁,获取锁成功就执行,不成功就不执行
3、countDownLatch
倒计数,初始化时初始化数量N,当线程调用countDown时,N减一,线程调用await(),进入阻塞,一直到N为0时,线程才能运行。多用于线程的协作。
4、CyclicBarrier
让一组线程到达一个屏障(也称同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续工作。
其中第一个参数为数量N,第二可参数为任务(可不填),当线程调用await时,线程进入等待,当等待的线程到达数量N时,执行任务(可不填),并且线程再同一时刻执行。
5、ReadWriteLock
读锁是一把共享锁,写锁是一把排他锁,当在读数据的时候,也就是在读加锁状态时,所有试图以读模式对它进行加锁的线程都可以得到访问权,但是如果线程希望以写模式对此进行加锁,他必须等到所有的线程释放锁。
当读写锁是写加锁状态时,在这个锁被释放之前,所有试图对他进行加锁的线程都会被阻塞。
通常, 当读写锁处于读模式锁住状态时, 如果有另外线程试图以写模式加锁, 读写锁通常会阻塞随后的读模式锁请求, 这样可以避免读模式锁长期占用, 而等待的写模式锁请求长期阻塞。
6、Semaphore
信号量,初始化指定信号量,线程通过调用acquire()方法获取许可,如果成功,就开始执行,如果不成功,就会阻塞。当执行完成之后,调用release()方法释放许可,别的线程才能够执行,主要用作限流。
7、Exchanger
主要是Exchangger的exchange方法,该方法是阻塞的,线程调用exchange时,线程就会被阻塞,等待其他线程交换,作用是两个线程交换消息,Exchanger只能是两个线程交换信息,多个线程不能用exchange
8、LockSupport
当前线程阻塞,调用LockSupport.port方法使当前线程阻塞,使用unport()方法唤醒指定线程,不过unport()方法可以先于port()方法使用,调用两次unport之后,port就停不住了
10、ThreadLocal
ThreadLocal是线程保存线程私有信息的一种方式,因为其在线程的整个生命周期内都有效,所以利用ThreadLocal去保存线程的一些私有信息,同时利用ThreadLocal可以在一个线程的不同模块之间进行信息传递,
ThreadLocal主要的原理是Thread中有一个Map,ThreadLocal指向当前对象,Thread类中的map以弱引用的指向ThreadLocal对象,而map保存线程的私有信息,每个线程都有自己独立的map,所以能保存自己的私有信息
11、线程池 Executor/ThreadPoolExecute
提供了一个线程队列,队列中保存着所有等待状态的线程,避免了创建和销毁的额外开销,提高了程序响应的速度
12、collections
在上篇文章中提过:Java中容器