CAS与原子类
-
CAS:Compare and Swap,它体现的是一种乐观锁的思想;
- 没有使用synchronized,不会陷入线程阻塞;
- 但是如果竞争激烈,会频繁尝试,影响效率;
- 必须配合volatile使用,拿到最新的值;
//不断的利用CPU尝试,避免了阻塞等待; while (true) {int 旧值 = 共享变量; //必须配合volatile使用,拿到最新的值;int 结果 = 旧值;if (comareAndSwap(旧值, 结果)) {//旧值相同,返回true;//旧值不同,返回false,其他线程已修改;} }
-
乐观锁:CAS,基于最乐观的估计,当别的线程修改,那就重新尝试【多核cpu】;
-
悲观锁:synchronized,基于最悲观的估计,防止其他线程来修改共享变量,给它加上把锁,我用完了再开锁;
synchronized优化:
- 每个对象投【class指针核Mark ward】,
- Mark Word平时存储这个对象的:哈希码,分代年龄;
- 当加锁的时候,就会替换为:标记位,线程锁记录指针,重量级锁指针,线程ID等;
- 每一个线程的栈帧,都会包含一个锁记录的结构,当对象加锁的时候,可以替换对象的Mark Word;
- 轻量级锁:多个线程访问的时间是错开的,当遇到线程同时访问的时候,会升级为重量级锁【无竞争】;
- 当无锁的时候,将mark word 复制给线程的锁记录,
- 使用CAS修改mark word 为锁记录地址;
- 修改锁状态;
- 锁膨胀【存在竞争】:
- 如果再尝试加轻量级锁的过程中,CAS操作无法成功【其他线程已经占用】,此时为就会将拥有锁的进行锁膨胀,升级为重量级锁;
- 同时,尝试加锁的线程会阻塞;
- 当拥有锁的,用轻量级解锁,失败,就释放重量级锁【唤醒阻塞线程】,开始竞争重量级锁;
- 重量级锁:
- 当线程陷入阻塞和唤醒时候,会降低效率;
- 所以当重量级锁被占用时,会尝试自旋,在短时间内,再度查看锁状态,多次所还是没有释放,还是会陷入阻塞;
- 偏向锁:
- 对于锁重注,相同的锁,不同的们,都需要进行锁记录地址核mark word的交换的优化;
- 优化:只有第一次使用的CAS将线程的ID设置到对象的markword头,之后发现这个线程id是自己就表示没有竞争,不需要重新CAS;
- 缺点多;
- 其他优化:
- 减少上锁时间,防止升级锁;
- 将一个锁,拆分为多个锁,并发度更高【减少锁的粒度】;
- 锁粗化,;
- 锁消除;
- 读写分离;