【JavaEE】了解常见的锁策略

本文详细介绍了乐观锁与悲观锁的工作原理,以及重量级锁与轻量级锁、自旋锁与挂起等待锁的区别。此外,还探讨了互斥锁、读写锁和可重入锁的概念,以及公平锁与非公平锁。通过解答面试题的形式,帮助读者掌握并发控制的关键概念。
摘要由CSDN通过智能技术生成

在这里插入图片描述

1、乐观锁 vs 悲观锁

乐观锁:
预测接下来锁竞争的概率很小—>在数据进行提交更新的时候,才会正式对数据是否产生并发冲突进行检测,如果发现并发冲突了,则让返回用户错误的信息,让用户决定如何去做
悲观锁:
预测接下来锁竞争的概率很大—>每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁

(锁竞争:两个线程对同一个对象加锁,产生阻塞等待)

2、重量级锁 vs 轻量级锁

轻量级锁:加锁解锁,过程更快,更高效
重量级锁:加锁解锁,过程更慢,更低效

3、自旋锁 vs 挂起等待锁

自选锁是轻量级锁的一种典型实现:
如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝试会在极短的时间内到来. 一旦锁被其他线程释放, 就能第一时间获取到锁

挂起等待锁是重量级锁的一种典型实现:如果锁被释放,不能第一时间获取锁,会进行等待

4、互斥锁 vs 读写锁

互斥锁:例如synchronized就是互斥锁,其加锁操作就只是单纯的加锁操作

读写锁:能够把读和写这两种加锁区分开

读写锁这样有什么好处?—>如果多个线程读同一个变量就不会涉及线程安全问题~

注意:
读写锁中约定:
(1)读操作和读操作之间,不会锁竞争,不会阻塞等待
(2)写操作和写操作之间,会引起锁竞争
(3)读操作和写操作之间,也会引起锁竞争

5、可重入锁 vs 不可重入锁

一个线程针对一把锁,连续加锁两次,出现死锁就是不可重入锁,没有死锁就是可重入锁

synchronizd是可重入锁:synchronized再加锁的时候会判定一下,当前线程是否为锁的拥有者,如果是,则直接放行

6、公平锁 vs 非公平锁

约定遵守先来后到的就是公平锁,不遵守先来后到的就是非公平锁~

7、常见面试题

1) 你是怎么理解乐观锁和悲观锁的,具体怎么实现呢?

悲观锁认为多个线程访问同一个共享变量冲突的概率较大, 会在每次访问共享变量之前都去真正加
锁.

// 第一次加锁, 加锁成功

lock();

// 第二次加锁, 锁已经被占用, 阻塞等待.

lock();
乐观锁认为多个线程访问同一个共享变量冲突的概率不大. 并不会真的加锁, 而是直接尝试访问数
据. 在访问的同时识别当前的数据是否出现访问冲突.

悲观锁的实现就是先加锁(比如借助操作系统提供的 mutex), 获取到锁再操作数据. 获取不到锁就
等待.

乐观锁的实现可以引入一个版本号. 借助版本号识别出当前的数据访问是否冲突. (实现细节参考上
面的图).

2) 介绍下读写锁?

读写锁就是把读操作和写操作分别进行加锁.

读锁和读锁之间不互斥.

写锁和写锁之间互斥.

写锁和读锁之间互斥.

读写锁最主要用在 “频繁读, 不频繁写” 的场景中.

3) 什么是自旋锁,为什么要使用自旋锁策略呢,缺点是什么?

如果获取锁失败, 立即再尝试获取锁, 无限循环, 直到获取到锁为止. 第一次获取锁失败, 第二次的尝
试会在极短的时间内到来. 一旦锁被其他线程释放, 就能第一时间获取到锁.

相比于挂起等待锁,

优点: 没有放弃 CPU 资源, 一旦锁被释放就能第一时间获取到锁, 更高效. 在锁持有时间比较短的场
景下非常有用.

缺点: 如果锁的持有时间较长, 就会浪费 CPU 资源.

4) synchronized 是可重入锁么?

是可重入锁.

可重入锁指的就是连续两次加锁不会导致死锁.

实现的方式是在锁中记录该锁持有的线程身份, 以及一个计数器(记录加锁次数). 如果发现当前加锁
的线程就是持有锁的线程, 则直接计数自增.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值