多线程复习

ABA问题

CAS进行操作的关键是通过值没有发生变化来作为"没有其他线程穿插执行"判定依据

但这种问题不够严谨,近端情况下,有另一个线程穿插进来,把值从A->B->A

ABA问题如果真的出现了,其实大部分情况下也不会产生bug,虽然另一个线程穿插执行,由于值又改回去了,此时逻辑上也不一定会产生bug

只要让判定的数值按照一个方向增长即可,有增有减就有可能出现ABA

但是针对账户余额这样的概念,本身就应该要能增能减,可以引入一个额外的变量"版本号"

约定每次修改都要让版本号自增

synchronized原理

1.锁升级

无锁->偏向锁(此时不是真的加锁,只是做了一个标记)->自旋锁->重量级锁

偏向锁不是真的加锁,当锁竞争出现的时候,偏向锁就会升级成轻量级锁,

这样就可以能够保证效率,又能保证线程安全,核心思想和"懒汉模式"一样

能不加锁就不加锁,加锁意味着开销

2.锁消除

编译器会针对当前你写的加锁的代码做出判定,如果编译器觉得这个场景不需要加锁,

此时就会把你写的synchronized给优化掉

3.锁粗化

synchronized里头代码越多就认为锁的粒度越粗

将连续多次对同一个对象加锁、解锁的操作,合并为一次范围更大的加锁操作,从而减少锁的获取和释放次数,提升性能。

Reentrantlock也是一个可重入锁,使用上和synchronized类似,但是需要手动解锁

优势:1.加锁时有两种方式lock和trylock

2.提供了公平锁的实现

3.提供了更强大的等待通知,搭配了Condition类,实现等待通知的

Semaphore(信号量)

开发中如果遇到需要申请资源的场景,就可以使用信号量来实现了,

锁本质上就是资源为一的信号量

加锁操作,P操作,1->0

解锁操作,V操作,0->1

CountDownLatch

这个东西主要适用于多个线程来完成一系列任务的时候,用来衡量任务的进度是否完成

比如需要把一个大的任务,拆成多个小的任务,让这些任务并发的去执行

就可以使用使用countDownLatch来判定这些任务是否全都完成

主要有两个方法

  1. await调用的时候就会阻塞,就会等待其他线程完成任务,所有线程都完成了任务以后,此时这个await才会继续往下走
  2. countDown告诉countDownLatch,我当前这个子任务已经完成了

copyOnWriteArrayList写实拷贝

比如两个线程使用同一份ArrayList,如果两个线程读就直接读

如果某个线程需要修改,就会把ArratList复制出一份副本,修改线程的话就修改这个副本,

与此同时另一个线程仍然可以读取数据,一旦修改完成就会使用修改好的这份数据,替代掉原来的数据

缺点:这个ArrayList不能太大(拷贝成本高),更适合多个线程读,一个线程去修改

应用场景:服务器的配置更新

ConcunrrentHashMap

ConcunrrentHashMap最核心的改进就是把一个全局的大锁改进成了每个链表独立的小锁,这样做,大幅度降低了锁冲突的概率。就是把每个链表的头节点作为锁对象,而java 8以前是基于分段式锁实现的

充分利用了CAS特性,把一些不必要加锁的环节给省略加锁了,比如需要用变量记录hash表中的元素个数,此时就可以使用原子操作(CAS)修改元素个数

针对读操作没有加锁,读和读,读和写之间都不会有锁竞争

针对扩容操作做出了单独的优化,原本HashMap扩容时需要把所有的元素都拷贝一遍,而ConcunrrentHashMap则是把扩容中一次搬运操作分成多次,每次只搬运一部分数据,避免这单次操作过于卡顿

相关推荐
敲敲了个代码2 小时前
多标签页强提醒不重复打扰:从“弹框轰炸”到“共享待处理队列”的实战
java·前端·javascript·面试·架构
Jackson@ML2 小时前
2026最新版Eclipse for Java安装使用指南
java·ide·eclipse
莫问前路漫漫2 小时前
JDK 核心实操指南:从安装配置到项目打包调试全流程
java·jdk
Getgit2 小时前
Linux系统的特点有哪些
java·linux·运维·网络·sql
APIshop2 小时前
Java获取item_get-获得某书商品详情接口
java·开发语言·python
weixin_395448913 小时前
tidl_import_mul_rmfsd_psd_u8_3x480x544_bise_raw_dynamic.txt
java·服务器·前端
Henry Zhu1233 小时前
Qt Model/View架构详解(四):高级特性
开发语言·qt·架构
txinyu的博客3 小时前
std::function
服务器·开发语言·c++
多多*3 小时前
图解Redis的分布式锁的历程 从单机到集群
java·开发语言·javascript·vue.js·spring·tomcat·maven