多线程进阶--面试常见知识点

1 常见的锁策略

1.1 乐观锁vs悲观锁

悲观乐观是对后续锁冲突是否频繁做出的预测。

如果预测接下来发生锁冲突的概率不大,就可以少做一些工作,就称为乐观锁;

如果预测接下来发生锁冲突的概率较大,就需要多做一些工作,就称为悲观锁。

1.2 重量级锁vs轻量级锁

重量级锁,锁的开销较大;轻量级锁,锁的开销较小。

通常,乐观锁就是轻量级锁,悲观锁就是重量级锁。

1.3 自旋锁vs挂起等待锁

自旋锁是轻量级锁的的一种典型实现,往往在用户态进行,例如使用一个while循环,不断判断当前锁是否被释放,如果没释放,就继续循环,如果已经释放,就获取到锁并结束循环。(忙等,消耗cpu但是换来了更快的响应速度);

挂起等待锁要借助系统api来实现,一旦出现锁竞争,就会在系统内核中执行一系列的操作(比如让这个线程进入阻塞状态,不参与cpu的调度,而阻塞的开销通常是很大的)。

1.4 读锁vs写锁

读锁:读的时候别的线程可以读,但是不可写。

写锁:写的时候别的线程不可以读,也不可以写。

1.5 公平锁vs非公平锁

当一堆线程等待锁释放想要拿到锁的时候,该按照什么策略拿呢?

公平锁:先来的线程先拿到锁。(先来后到)

非公平锁:每个线程以相同的概率竞争锁。

以上策略都是锁的一些特点,那前面说过的synchronized属于哪种锁呢?

1、对于"悲观乐观"是自适应的。

2、对于"重量轻量"是自适应的。

3、对于"自旋挂起"是自适应的。

4、不是读写锁。

5、是可冲入锁。

6、是非公平锁。

对于初始情况,synchronized会预测锁冲突的概率不大,此时以乐观锁的模式来运行(也就是轻量并且自旋的);如果后续锁冲突的概率加大,那么此时就会自适应的变为悲观锁(也就是重量挂起的)。

2 CAS

CAS就是compare和swap,也就是比较并且交换,那它比较的是什么呢?是内存和寄存器中的值。

CAS(M,A,B):比较M和A的值,如果相同,就把M和B的值交换,返回true;如果不同,就什么都不做,直接返回false。

这是CAS的伪代码:

CAS本质上是cpu提供的一个指令,是具有原子性的,之后又被操作系统封装,提供api,又被JVM封装,也提供api,最后供程序员使用。

既然CAS是具有原子性的,那么它也可以解决"线程安全"问题,从而在一些场景中代替加锁策略,基于CAS实现"线程安全"的编程称为无锁编程。这样做的好处是什么呢:不仅可以保证线程安全,同时比加锁的效率更高;但是,也存在一些缺点:1、代码会更复杂,不好理解 2、仅使用于一些场景,不如加锁普适性强。

2.1 CAS的关键问题:ABA问题

什么是ABA呢?当一个线程将数据A取出,经过一系列操作后把它变为B,但是最后又通过一系列操作将它变回A,那么对于另一个执行CAS操作的线程来说,可能会认为这个数据是没发生过变化的(虽然有的时候也不会出现bug),这种问题就是ABA问题。

此时,左侧的CAS中value的值不等于oldValue的值,就不执行任何操作,直接返回false。但是如果发生ABA问题,例如此时恰好有个人又给我转了500元,那么我的value又变回1000,等于oldValue,再次扣款,这就出现了很严重的bug,本来我只打算取500,但是现在取了1000!!

那又该怎么解决这个问题呢?

很简单,只需要让判定的数值按照一个方向变化即可(不要出现反复横跳,一会加一会减就可能会出现ABA问题)。在上述这个例子中,我们只需要将CAS的判定条件改为版本号,初识版本号为v1,每执行一次操作,版本号就会加1,那么,只要有其它线程穿插执行,版本号一定不等于old版本号,此时一定不会执行交换操作,而是会直接返回false,bug顺利解决。

3 信号量Semaphore

信号量是操作系统中比较重要的概念,其实信号量就是一个计数器,描述了"可用资源"的个数,每次申请一个可用资源,就要让信号量减1(P操作),每次释放一个操作,就要让信号量加1(V操作),那如果信号量已经为0的情况下继续申请资源(使用P操作)会发生什么呢?此时就会阻塞等待,直到其它线程释放一个资源(使用V操作),才能继续往下执行。

前面提到过的锁其实就是一种特殊的信号量,锁就是可用资源为1的信号量,所以一旦加锁,其它线程就会发生阻塞,因为加锁相当于使信号量减1,而此时信号量一共就是1,所以直到该线程释放锁,也就相当于执行V操作,其它线程才能获得锁

相关推荐
jiayong2312 分钟前
前端面试题库 - JavaScript核心基础篇
前端·javascript·面试
JAVA面经实录91714 分钟前
Java多线程并发高频面试100题(完整版·含答案·背诵版)
java·开发语言·面试
XiYang-DING17 分钟前
【Java EE】TCP—流量控制和拥塞控制
java·tcp/ip·java-ee
BIG_PEI37 分钟前
检查并安装Redis
java
大貔貅喝啤酒39 分钟前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
奋斗的小方40 分钟前
Java基础篇09:项目实战
java·开发语言
海兰41 分钟前
【第21篇-续】graph-Stream-Node改造为适配openAI模型示例
java·人工智能·spring boot·spring·spring ai
vKd0Ff21L44 分钟前
如何在Dev-C++中设置TDM-GCC为默认编译器第九十一篇
java·jvm·c++
武子康1 小时前
Java-221 RocketMQ 消息存储核心原理:CommitLog、ConsumerQueue、IndexFile 与消息过滤机制
java·大数据·分布式·消息队列·rabbitmq·rocketmq·java-rocketmq
北风toto1 小时前
为什么 IntelliJ IDEA Community 无法开发 Vue?——附解决方案
java·vue.js·intellij-idea