并发与多线程
1线程的同步与互斥。
解决线程的同步与互斥 synchronied 和cas乐观锁 还有 lock
cas是读取数据的时候不进行加锁 写会数据的时候看是否发生了改变,若没有被其他线程修改择写回 ,若被其他线程修改,择重新读取;比较和写回的操作是操作系统的源语实现的保证过程中不会有别的操作,但是容易出现ABA问题;解决的办法是添加标志位或者时间戳 判断数据时候进行的修改。
Synchronized 是如何保证线程的临界区的呢?
Synchronized 是对对象进行加锁,在jvm中对象是分为三块区域的,对象头 实例数据 对其填充,对象头中有锁标志位和指向Monitor对象的地址;当Monitor对象被线程占用以后就会处于锁定状态,owner就会指向持有Monitor对象的线程,Monitor还有两个队列;
一个是进入队列,一个是等待队列;当Synchronized 作用在方法上时,在字节码中是通过acc_Synchronized 字节码标志实现的,Synchronized 用在代码块上时,是通过monitorenter和monitorexit实现的;Synchronized 获取锁的方式有锁升级的方式;先使用偏向锁 优先同一线程再次获取锁,如果失败 就升级为cas轻量级锁 ,在失败就自旋防止挂起;都失败 就会进行重量级锁 ;
2下来介绍AQS和lock
AQS队列同步器AQS有一个标志位 值为1时表示有线程占用,其他线程需要进入同步队列等待,同步队列是一个双向链表,当获得锁的线程需要等待某个条件执行时,会进入等待队列,等待队列可以有多个,当条件满足时,锁的竞争,线程会从等待队列进入同步对列进行Reentrantlock 就是基于aqs实现的;内部有公平锁和非公平锁,差别在于新来的线程比有没有可能在同步队列中等待的线程更早的获取锁。
3线程池的使用场景
newFixedThreadpool -- 固定线程数,无界队列,适用于任务数量不均匀的场景,对内存压力不敏感,对系统负载比较敏感的场景;
newCachedThreadPool 无限线程数 ,适用于要求低延迟的短期任务。
newSingleThreadExecutor 单个线程的固定线程池, 适用于保证异步执行顺序的场景。
newScheduledThreadPool 适用于定期执行任务场景,支持固定频率和固定延迟。
newWorkStealingPool 使用forkjoinpool,多任务队列的固定并行度,适合任务执行时长不均匀的场景。
4juc 工具类
基本数据类型如Atomiclong 是通过unsafe类实现的,基于cas,unsafe类是底层工具类,java中很多包中都有这个类,unsafe类实现了cas的操作,
Long Adder基于Cell,分段锁思想,空间换时间,更适合高并发场景。
ReentrantLock 是独占锁, Semaphore是共享锁。
CompletableFuture 支持流式调用,多future组合,可以设置完成时间。