多线程复习

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则是把扩容中一次搬运操作分成多次,每次只搬运一部分数据,避免这单次操作过于卡顿

相关推荐
enjoy嚣士14 分钟前
springboot之Exel工具类
java·spring boot·后端·easyexcel·excel工具类
Thera77715 分钟前
C++ 高性能时间轮定时器:从单例设计到 Linux timerfd 深度优化
linux·开发语言·c++
罗超驿26 分钟前
独立实现双向链表_LinkedList
java·数据结构·链表·linkedlist
炘爚1 小时前
C语言(文件操作)
c语言·开发语言
阿蒙Amon1 小时前
C#常用类库-详解SerialPort
开发语言·c#
盐水冰1 小时前
【烘焙坊项目】后端搭建(12) - 订单状态定时处理,来单提醒和顾客催单
java·后端·学习
凸头1 小时前
CompletableFuture 与 Future 对比与实战示例
java·开发语言
wuqingshun3141591 小时前
线程安全需要保证几个基本特征
java·开发语言·jvm
Moksha2622 小时前
5G、VoNR基本概念
开发语言·5g·php
努力也学不会java2 小时前
【缓存算法】一篇文章带你彻底搞懂面试高频题LRU/LFU
java·数据结构·人工智能·算法·缓存·面试