多线程高并发(上)
其他
2021-01-30 13:45:44
阅读次数: 0
本文涵盖了进程内多线程高并发常用技术。
简述
启动线程的3种方式
1:Thread
2:Runnable
3:Executors.newCacheThread
sleep(自动复活到就绪状态)
yield(让出一下cpu,返回到就绪状态)
join
OS启动的线程数要大于java启动的线程(GC线程)
状态:ready,running,new,terminated,waiting,blocked,timewaiting
synchronized
hotspot使用对象头拿出两位记录
锁升级
特性
有序性
既可保证原子性,又可保证可见性
可重入锁
举例:父子类都为sychronized,锁的是子类对象,调用父类还是锁的子类
出现异常锁会被释放
锁定目标
synchronized(o)
synchronized(this)
synchronized(T.class)
同一个classloader空间把T.class加载到内存是单例的,不同classloader之间不能访问
加了就不用加volatile
锁升级
偏向锁:对于第一个对象,刚开始只记录线程ID
如果有线程争用,升级为自旋锁,默认自旋10次,之后升级为重量级锁,成为等待状态,不占CPU
锁只能升级,不能降级
执行时间短(加锁代码),线程数少,用自旋。执行时间长,线程数多,用系统锁
优化
细化,由锁方法到锁变量
避免对象的引用发生改变
volatile
作用
保证线程可见性
MESI缓存一致性协议
禁止指令(二进制码)重排序
a=new A();申请内存,初始化,赋值
保证原子性并不能保证重排序
读屏障或者写屏障可以防止指令重排序
不能保证原子性,要想保证原子性就用synchronized或者AtomicInteger
CAS
无锁,优化自旋
类本身是原子性的,但是不能保证多个方法连续调用是原子性的
CAS操作是CPU指令级别的支持
ABA问题:1、加版本号;2、AtomicStampedReference
如果基础类型无所谓;引用类型
Unsafe
靠CPU的原语来实现
并发特别高的情况:longadder(分段锁)->Atomic(无锁)->Sync(锁)
分段锁也是cas操作
ReentrantLock
finally unlock
ReentrantLock尝试某些次
可以对interrupt()方法做出响应
true公平锁,可以指定不公平或者公平;sync只有不公平
reen vs sync
cas vs sync锁升级
trylock
interrupt()
可以代替sync
公平和非公平锁
reen condition
CountDownLatch
await
countDown(原子性)
与join
join必须要等到线程结束
barrier
Phaser
遗传算法
barrier的升级版
readwritelock(读写锁)
共享锁+排它锁
stampedLock(升级态)
semaphore
acquire、release
令牌、限流
exchanger
两两交换
LockSupport(JDK1.6)
park unpark
ArrayList非线程安全
notify不释放锁
wait释放锁
condition
lock.newCondition生成一个等待队列
生产者唤醒消费者,消费者唤醒生产者
AQS(CLH)
核心是state,volatile int
state随着子类变化
是一个双向链表线程队列
向队列加东西用的是compareAndSetState
compareAndSetTail 自旋 用CAS代替了锁定整条链表的操作
varhandler
指向某对象的引用
compareAndSet int 为原子性操作
1.通过handle普通属性也可以完成原子性操作
2.比反射快直接操作二进制码
ThreadLocal
set get不能获取到对象
声明式实物,保证同一个connect
引用
强
new A();
软
System.gc属于fullGC
SoftReference内存不够用先回收一次,在直接干掉,做缓存使用
弱
只要垃圾回收就会回收
ThreadLocal set() extend weakreference
内存泄漏,漏了一块
tl消失,ThreadLocal回收 务必要tl.remove
虚
管理堆外内存,用来回收堆外内存
PhantomReference
垃圾回收看到就干掉,被干掉后收到一个通知(队列里添加一个值),队列里有值了就可以回收 堆外内存了Unsafe.allocMemory Unsafe.freeMomory
线程池
callable
和callable一样,只不过callable有返回值
用来拿callable的执行结果
future=service.submit异步操作
future.get阻塞
FutureTask
FutureTask->RunnableFuture->FutureCallable
CompletableFuture
一种任务的管理类
ForkJoin
线程池(2种)
ThreadPollExecutor(7个参数)
池子用的是hash
work
AddWorker
外层自旋,数量+1;启动worker加锁
thread
runnable AQS
参数
核心线程数coreThreadSize
核心线程中的线程,即使时间到了,也会占着
最大线程数maxThreadSize
生存时间liveTime
生存时间单位TimeUtil
任务队列
ArrayBlokingQueue
LinkedBlokingQueue(最大值是MAX_INTEGER)
线程工厂defaultThreadFactory
拒绝策略
线程池忙,任务队列满了,执行拒绝策略
ForkJoinPool
大任务分解成小任务,在集合
ForkJoinTask
RecursiveAction
Executor(线程池的工厂)
Single
LinkedBlockingQueue
Cached
SynchrousQueue
fixed
LinkedBlockingQueue
sheduled
DelayedWorkQueue
newWorkStealingPoll
每个线程都有自己的队列,自己的队列里面没有了去别的偷
push pop不需要阻塞 但是poll需要
底层用的是ForkJoinPoll
很像mapReduce
定时任务
Quartz
cron
Thread
一般情况下线程数=CPU*使用比*(1+W/C)
并发是任务提交,并行是任务执行,并行是并发的子集
Linux线程调度方法:1、优先级;2、按时间片(默认);3、实时
execute方法
核心线程->队列->非核心线程
disruptor
特点
对比concurrentLinkedQueue实现
JDK中没有concurrentArrayQueue
只需要维护sequenece
环形队列ringbuffer
12%8=12&(8-1)
event
eventFactory
直接覆盖,不用清楚旧的数据,降低GC频率
eventHandler
ProducerType
ProducerType.MULTI
ProducerType.SINGLE
等待策略(8种)
BlockingWait
YieldingWait
SleepingWait
JMH
parrelStream.foreach->foreach
容器
collection
list
copyOnWriteArrayList
写时复制
SynchronizedList
ArrayList
线程不安全
LinkedList
set
queue(针对高并发)
queue与list相比
添加了offer,peek,poll对线程友好的API
concurrentLinkedQueue
CAS
offer添加,线程安全
poll取并且remove,线程安全
peek取不会remove,线程安全
天生实现生产者,消费者模型
PriorityQueue
用堆实现
DelayQueue
阻塞
按时间进行任务调度
用PriorityQueue实现
ArrayQueue
BlockingQueue(线程安全)
LinkedBlockingQueue
put,阻塞
take,阻塞
底层用LockSupport.park实现
使用await,Condition->park
ArrayBlockingQueue
PriorityBlockingQueue
SynchrousQueue
容量为0
两个线程直接交换数据,手对手
TransferQueue
LinkedTransferQueue(等着人把资源取走才行,面对面付款,多人手对手)
Map
vector
hashtable和vector自带锁,基本不用
线程不安全
hashmap
hashmap
synchronizedHashMap,加锁了
concurrentHashMap
效率提高在读上面
无序
分段锁
CAS
将原本的一整个的Entry数组分成了若干段,分别将这若干段放在了不同的新的Segment数组中(分房间),每个Segment有各自的锁,以此提高效率
concurrentSkipListMap
有序
内部是SkipList(跳表)结构实现
转载自blog.csdn.net/u014162993/article/details/112140088