java并发复习笔记总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java并发复习笔记总结相关的知识,希望对你有一定的参考价值。

本文地址:http://www.cnblogs.com/maplefighting/p/7941885.html 

1、volatile:轻量级的synchronized,不会引起线程上下问切换

为了提高速度,处理器不直接和内存进行通信,而是先将系统内存的数据读到内部缓存后再操作。声明了volatile,jvm向处理器大宋Lock前缀指令,将变量在缓存行的数据写到系统内存,每个处理器通过总线传播的数据检查自己缓存的值是否过期。

2、volatile实现原则:

(1) Lock前缀指令会引起处理器缓存回写到内存。

(2) 一个处理器的缓存回写到内存会导致其他处理器的缓存失效。

3、锁的状态,级别从低到高为:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态

      锁可以升级但不能降级

      偏向锁:只有一个线程进入临界区

      轻量级锁:多个线程交替进入临界区     CAS

      重量级锁:多个线程同时进入临界区

4、处理器实现原子操作:(1) 总线锁    (2) 缓存锁定

5、Java实现原子操作:(1) 锁      (2) 循环CAS

6、volatile:写happens-before 读

写一个volatile变量时,JMM (Java内存模型) 会把该线程对应的本地内存中的共享变量刷新到主内存中。

读一个volatile变量时,JMM会把本地内存置无效,从内存读取共享变量。

7、CAS:先操作比较与预期的值是否一样,一样就设置,不一样就继续循环(CompareAndSet)

      CAS同时具有volatile读与写到内存语义

8、happens-before 先行规则

(1) 程序顺序规则:一个线程的每个操作happens-before于该线程中的任意后序操作

(2) 监视器锁规则:对一个锁的解锁happens-before于任意后序对这个锁的加锁

(3) volatole变量规则:对一个volatile域的写happens-brfore于读

(4) 传递性:A happens-before B,B happens-before C => A happens-before C

(5) start()规则:如果A执行 ThreadB.start(),那么 A线程的ThreadB.start()  happens-before B的任意操作

(6) join()规则:如果A执行ThreadB.join()并成功返回,那么B中任意操作happens-before 于A从 ThreadB,join()操作成功返回

9、上下文切换:任务从保存到加载的过程

减少上下文切换有无锁并发编程,CAS算法,使用最少线程和使用协程

10、Java内存模型

线程之间的共享变量存储在主内存中,每个内存都有一个私有的本地内存,本地内存存储了该线程读写共享变量的副本,本地内存只是一抽象,并不真实存在。

11、final 内存语义

(1) 在构造函数内对final 域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,不能重排序。

(2) 初次读一个包含final域对象的引用,与随后初次读这个fianl域,不能重排序。

 12、as-if-serial 语义保证单线程内程序的执行结果不被改变

        happens-before 保证正确同步的多线程程序执行结果不被改变

13、HashMap 

jdk1.7多线程put会死循环,因为Entry链表形成环数据结构,Entry的next永远不为空

没使用Synchronized,可接受 null 的 key 和 value

&   默认容量为16,扩容2倍     自定义的hash

HashTable 

使用 Synchronized,key 和value 都不能 null

%   默认容量为11,扩容两倍+1     hashcode

ConcurrentHashMap

段分锁,提高并发访问效率

segment->可重入锁,2^n长度  包含HashEntry的链表结构

14、ConcurrentHashMap

(1) 由 Segment 和 HashEntry 构成   , Segment长度为2的n次方,jdk1.7 Segment会锁住多个HashEntry

(2) get:先经过一次再散列,根据值使用散列运算定位到Segment,再通过散列算法定位到元素。get里面的共享变量都定义为volatile类型,所以不用加锁

(3)定位HashEntry 和定位Segment 都是与数组长度-1 相与,但是相与的"值"不一样。Segment使用的是元素的hashcode 通过再散列后的值的高位,定位HashEntry 直接使用再散列后的值。目的:避免两次值一样

(4) put 必须加锁,定位到Segment ,判断是否HashEntry 要扩容,然后再添加

(5) 第一次put时才初始化

15、ConcurrentHashMap

jdk1.8改进:(1)取消Segment字段,使用volatile HashEntry<K,V>[] 数组元素作为锁         (2) 改为table数组 + 单向链表 + 红黑树,节点超过8会用红黑树

jdk1.7

put:(1) A tryLock 成功获得锁,把hashEntry插入

(2)获取锁失败,执行scanAndLockForPut方法,重复执行tryLock,多处理器重复64,单处理器重复1次,超过时,挂起线程

size:(1)不加锁,计算两次,相同说明准确。不一样,给每个Segment加锁,再计算

modCount    put,remove,clean时会加1

jdk1.8

size:元素个数保存在baseCount,部分元素的变化个数保存在CounterCell数组中,累加

 a、新增节点后,链表的元素个数达到8,就转换成红黑树,不过转换之前,如果数组长度小于阀值,默认为64 (数组长度大于64,才会考虑转换红黑树),则会扩大两倍,并触发transfer

b、元素个数0.75倍数组,扩容 (hashMap也一样)

16、ReentrantLock 可重入锁,分为公平锁和非公平锁

a、公平锁:队列顺序,等待久的先

      非公平锁:可以抢占   CAS

b、公平锁和非公平锁,释放最后都要写一个volatile变量

      公平锁,获取时会先读volatile变量。非公平锁获取时,会用CAS更新volatile变量

c、非公平锁用CAS。  公平锁加个判读去年当前节点是否有前驱节点 hasQueuedPredecessors()方法

d、非公平锁可能造成线程"饥饿",但是极少的线程切换,保证吞吐量,吞吐量更大。

17、ReetrantReadWriteLock读写锁

高16位读,低16位写  AQS           可重入

锁降级:把持当前拥有的写锁,再获取读锁,稍后释放锁。目的:保证数据的可见性

18、队列同步器 AQS (AbstractQueuedSynchronizer)  构建锁和或其他同步组件的基础架构   ReetrantLock,Condition,ReetrantReadWriteLock等

同步器提供  getState(),setState( .... ),conpareAndSetState( .... )

重写AQS时,可以使用CAS等

实现:a、同步队列  双向链表  ,CAS设置尾节点

   b、独占式同步状态获取与释放   CAS入队enq(node),出队时,每个node都在自旋

   c、共享式 <-- 释放同步线程CAS

内部使用volatile修饰 int state 表示同步状态

共享式同步状态:tryAcquireShared(arg) >= 0时,能获得同步状态

获取同步状态失败进入同步队列(addWaiter),先CAS设置,失败进入enq方法。出队列不需要CAS

19、ConcurrentLinkedQueue   不要用size(),会遍历全部

(1)非阻塞,入队永远返回true,用CAS

不是每次节点入队后都将tail节点更新为尾节点,而是当tail与尾节点距离>=HOPS常量时才更新,提高入队效率

出队仅没有元素时才会更新head节点,减少CAS

(2)阻塞队列

插入:队列满时阻塞       移除:队列空时阻塞

使用通知模式  condition   消费者消费通知生产者

阻塞生产者通过LockSupport.park实现

20、Condition接口    是AQS的内部类

condition定义了await()和signal(),signalAll() 方法

获取一个condition要通过Lock的newCondition。 

一个condition包含一个等待队列,增加节点没有CAS保证,由await()锁保证线程安全

(1) await()时会使当前线程从同步队列首节点构造成一个新节点,加入等待队列中。

(2) 调用condition的signal() 方法时,将等待队列中首节点加到同步队列中

21、LockSupport 每个线程都有一个Park实例, unPark可以先于Park出现

基于Unsafe实现的

使用Park使线程挂起,释放(1) 其他线程调用unPark,(2) 线程中断,(3) park方法立即返回

22、Fork/Join框架:分割任务,执行并合并结果。    工作窃取算法

23、CycleBarrier 所有线程彼此等待    CountDownLatch:只要报到

允许一个或多个线程等待其他线程完成操作

CountDownLatch的计数器只使用一次

CycleBarrier可以reset(),跟join差不多(AQS,ReetrantLock)

等多有线程都运行到下一个步骤前等待

24、控制并发线程数的Semaphore (信号量) AQS

用来控制同时访问特定资源的线程数量

25、Synchronize和Lock的区别

(1) Lock的锁是Java写的控制锁的代码。  Synchronize是托管给jvm的,Java关键字

(2) Synchronize在异常时,jvm会释放锁。  Lock不会主动释放锁,要手工释放。

(3) Synchronize 悲观的排他锁。    Lock有读写锁,公平锁,非公平锁

26、线程池 ThreadPoolExecutor

好处:(1) 降低资源消耗  (2) 提高响应速度  (3) 提高线程可管理性

流程:a、判断核心线程池线程是否执行任务。  创建线程需要获取全局锁

    b、是的话,判断工作队列是否已满。   目的:尽可能避免获取全局锁

    c、是的话,判断线程池的线程是否都处于工作状态

    c满了就调用饱和策略。默认抛出异常

提交任务:execute()  不返回值     submit() 返回future类型的对象

关闭池:shutdownNow  停止所有     shutdown 中断没有执行任务的线程

线程池最大容量   AtomicInteger类型,capacity前三位为标志位,所以最大为(2^29) - 1

状态分别为:RUNNING,SHUTDOWN,STOP,TIDYING,TERMINATED

参数:corePoolSize 核心线程数     maximumPoolSize 最大线程数    keepAliveTime 最大存活时间    rejectExecutionHandler 任务拒绝处理策略

27、Executoe框架

应用框架通过Executor框架控制上层调度,而下层调度由操作系统内核控制

使用流程:主线程先创建Runnable或Callable接口,然后交给ExecutorService执行,返回Future接口对象

28、ThreadLocal

一个线程可以根据ThreadLocal查询到绑定在这个线程的一个值,可用于数据库连接

提供get和set访问与当前相关的局部变量。变量是保存在线程中的threadLocals (threadLocalMap类型的)

ThradLocalMap.Entry弱引用,随时可能被回收

get先得到当前线程的ThreadLocalMap,再根据 ××.Entry = get(this) 得到值

29、Synchroinzed:jvm基于进入与退出使用monitorenter和monitorexit指令实现,偏向锁,轻量级锁

30、atomic×××

value成员都是volatile   CAS

基本方法:get/set,compareAndSet  (unsafe.compareAnsSwapInt(....) )

CAS:调用UnSafe的方法,不是用Java实现,而是JNI调用操作系统原生程序

31、CopyOnWriteArrayList  占用内存

当我们往一个容器添加元素时,不直接往当前容器添加,而是先copy复制一个新的容器,添加完后,再将原容器指向新的。

并发读不用加锁。添加时要加锁,否则多线程会copy出多个副本。

如果在最后添加元素,则用Array.copyOf()。如果在中间插入,则用System.arraycopy分两段复制。

应用读多写少并发场景,如白名单,黑名单

 

参考书籍:Java并发编程的艺术(推荐),juc包源码

 

--------------------------------------------------------------------------------------------------------------

 

以上为maplefighting个人笔记整理,如有出错,欢迎指正

 

以上是关于java并发复习笔记总结的主要内容,如果未能解决你的问题,请参考以下文章

笔记总结计算机系期末复习专业课学习算法与其他笔记

笔记总结计算机专业面向期末考试复习笔记专业课学习笔记课外算法与其他学习笔记

CGBTN2111-DAY01总结复习

CGBTN2110-DAY01总结复习

CGBTN2111-DAY01总结复习

并发编程复习笔记