Java 锁 面试题(ReentrantLock、synchronized)

news/2025/3/19 10:39:32/

Java 锁 面试题(ReentrantLock、synchronized)

  • 1. 锁
  • 2. ReentrantLock
    • 2.1 ReentrantLock 的实现原理
    • 2.2 AQS 是什么?
    • 2.3 CAS 是什么?
  • 3. synchronized
  • 3.1 synchronized 的实现原理
    • 3.2 synchronized 的锁升级过程
      • 3.2.1 无锁
      • 3.2.2 偏向锁
      • 3.2.3 轻量级锁
      • 3.2.4 重量级锁
      • 3.2.5 自旋锁
    • 3.2 synchronized 和 volatile 的区别
  • 4. synchronized和ReentrantLock的区别
    • 4.1 什么是可重入锁?
    • 4.2 什么是乐观锁和悲观锁?(简要回答)
    • 4.3 什么是自旋锁?(简要回答)
    • 4.4 什么是公平锁和非公平锁?(简要回答)
    • 4.5 什么是死锁?如何避免(简要回答)




1. 锁

常用和锁、线程安全相关的工具:synchronized、ReentrantLock、AtomicInteger、AtomicLong、CopyOnWriteArrayList、CopyOnWriteArraySet、ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet

2. ReentrantLock

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gkCZHf8l-1685216539209)(…/images/imagehello.png)]

2.1 ReentrantLock 的实现原理

ReentrantLock 是基于 AQS(AbstractQueuedSynchronizer)实现的,AQS 是一个用于构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器,比如常用的 ReentrantLock、Semaphore、CountDownLatch、ReentrantReadWriteLock、ThreadPoolExecutor 等。

2.2 AQS 是什么?

AQS 内部维护了一个 volatile int state 和一个 FIFO 队列,state 用于表示同步状态,FIFO 队列用于存放获取同步状态失败的线程。

2.3 CAS 是什么?

CAS(Compare And Swap)是一种无锁算法,当多个线程尝试使用 CAS 同时更新同一个变量时,只有其中一个线程能更新变量的值,而其它线程都失败,失败的线程并不会被挂起,而是被告知这次竞争中失败,并可以再次尝试。

3. synchronized

3.1 synchronized 的实现原理

Java 中的对象监视器(monitor)实现的。每个对象都有一个 monitor,monitor 可以和任意个线程关联,线程可以通过调用对象的 wait() 和 notify() 方法来与 monitor 进行交互。

线程执行 wait() :会让自己进入 monitor 的等待队列,并且释放 monitor 上的所有锁。

线程执行 notify() :会从等待队列中随机选择一个线程,并将其唤醒,被唤醒的线程则进入 monitor 的锁定队列,等待获取 monitor 上的锁。当线程执行完毕退出 synchronized 代码块时,会释放 monitor 上的所有锁,此时被唤醒的线程可以获取 monitor 上的锁,继续执行。

3.2 synchronized 的锁升级过程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1amvKo6G-1685216539210)(…/images/image-111.png)]
synchronized 的锁升级过程分为四个阶段:无锁、偏向锁、轻量级锁和重量级锁。

简述升级过程:
无锁

偏向锁:当一个线程访问同步块并获取锁时,如果该同步块没有被锁定,那么该线程会尝试获取该同步块的偏向锁,并将对象头中的 Mark Word 设置为偏向锁。如果该同步块已经被其他线程锁定,那么该线程会尝试获取该同步块的轻量级锁。

轻量级锁:当一个线程尝试获取一个同步块的锁时,如果该同步块没有被锁定,那么该线程会尝试获取该同步块的轻量级锁,并将对象头中的 Mark Word 设置为指向线程栈帧的指针。如果该同步块已经被其他线程锁定,那么该线程会尝试获取该同步块的重量级锁。

重量级锁:当一个线程尝试获取一个同步块的锁时,如果该同步块已经被其他线程锁定,那么该线程会进入阻塞状态,直到该同步块的锁被释放。在重量级锁的实现中,JVM 会将对象的 Mark Word 指向一个互斥量,从而实现线程的阻塞和唤醒。

3.2.1 无锁

无锁状态下,线程可以随意进入临界区,不需要进行任何同步操作。

3.2.2 偏向锁

偏向锁(只使用于没有竞争的场景下),如果一个现场获取了锁,在未来的一段时间内,该线程可能在此获取这个锁,JVM会偏向于这个线程。

3.2.3 轻量级锁

轻量级锁(只使用于没有竞争的场景下),如果一个现场获取了锁,在未来的一段时间内,该线程可能在此获取这个锁,JVM会偏向于这个线程。

3.2.4 重量级锁

重量级锁(只使用于有竞争的场景下),如果一个现场获取了锁,在未来的一段时间内,该线程可能在此获取这个锁,JVM会偏向于这个线程。

3.2.5 自旋锁

自旋锁是指当一个线程尝试获取某个锁时,如果该锁已被其他线程占用,就一直循环等待,直到该锁被释放为止,线程不会被挂起,而是处于忙等状态,因此自旋锁一般适用于锁保护的临界区比较小的情况。

3.2 synchronized 和 volatile 的区别

synchronized 用于保证同一时间只有一个线程可以访问被 synchronized 修饰的代码,而 volatile 用于保证多个线程之间对变量的可见性。

4. synchronized和ReentrantLock的区别

  1. synchronized是Java关键字,ReentrantLock是类
  2. synchronized相比,ReentrantLock提供了一些高级功能,主要有以下三项:
    1. 等待可中断,持有锁的线程长期不释放的时候,正在等待的线程可以选择放弃等待,这相当于synchronized来说可以避免出现死锁的情况
    2. 公平锁,多个线程等待同一个锁时,必须按照申请锁的时间顺序获得锁,synchronized锁非公平锁,ReentrantLock默认的构造函数是创建的非公平锁,可以通过传入true创建公平锁
    3. 锁绑定多个条件,一个ReentrantLock对象可以同时绑定多个Condition对象
  3. synchronized会自动释放锁,ReentrantLock需要手动释放锁,如果不释放锁,就有可能导致死锁

4.1 什么是可重入锁?

可重入锁是指同一个线程可以多次获得同一把锁,而不会被阻塞。ReentrantLock和synchronized都是可重入锁。

4.2 什么是乐观锁和悲观锁?(简要回答)

概念,具体实现方式有很多种。
乐观锁认为数据一般不会造成冲突,所以不会上锁,而悲观锁认为数据一般会造成冲突,所以会上锁。

4.3 什么是自旋锁?(简要回答)

自旋锁是指尝试获取锁的线程不会立即阻塞,而是采用循环的方式去尝试获取锁,这样的好处是减少线程上下文切换的消耗,缺点是循环会消耗CPU。

4.4 什么是公平锁和非公平锁?(简要回答)

公平锁是指多个线程按照申请锁的顺序来获取锁,非公平锁是非顺序的,非公平锁的优点在于吞吐量比公平锁大。

4.5 什么是死锁?如何避免(简要回答)

死锁是指两个或者两个以上的线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,这些线程都将无法推进下去。
避免死锁的方法:

  1. 设置超时时间
  2. 死锁检测tryLock






我的Github地址,欢迎大家加入我的开源项目,或者(在我的主页联系我)加入你们的开源项目,点点Github-Stars。

\开源项目名称依赖类型版本号描述
1spring-boot-starter-triepom1.0.0-SNAPSHOT特定需求下查询速度远超开源检索工具,innodb下B+树或者ES中倒排索引无法与之比拟.
2spring-boot-starter-triejar1.0.0-M1提供了基于SpringCloud的服务节点,可以通过Nacos注册中心进行服务发现,实现了树的动态扩容与缩容,以及服务的动态上下线。
3Data-Providerpom1.0.0-SNAPSHOT提供了多种数据源的查询,以及数据的类型同步,作为一个Jar可以依赖在其他服务上动态的提供数据。

http://www.ppmy.cn/news/96913.html

相关文章

【STM32F103ZE实验】【实验1】点亮LED

STM32CubeMx生成keil工程 步骤1:打开STM32CubeMx, 选择MCU类型 步骤2: 设置Debug类型 步骤3: 选择时钟源 步骤4: 配置时钟 步骤5: 配置GPIO控制LED 首先配置PE5 点击GPIO_Output进行相关配置&#…

Jmeter下载安装---Windows系统

Jmeter下载安装---Windows系统 jmeter是什么Jmeter下载安装安装jmeter前置必须jdk8Jmeter下载 jmeter插件环境变量配置 jmeter是什么 Apache JMeter 是 Apache 组织基于 Java 开发的压力测试工具,用于对软件做压力测试;在接口及性能测试中广泛使用&…

QThread Class

QThread QThread类枚举类型成员函数可重写函数公共槽信号静态成员函数保护函数静态保护函数QThread简单案例1QThread简单案例2 QThread类 标准头文件&#xff1a;#include <QThread> qmake: QT core 继承(父): QObject枚举类型 线程的优先级 enum Priority { IdlePri…

scipy库统计模块stats

# 统计相关模块stats sp.stats.norm.rvs()#标准正态分布 sp.stats.norm.fit()#估算正态分布的参数 sp.stats.norm.pdf()#计算对应位置的概率密度 sp.state.norm.ppf()#找到标准正态分布中概率恰好为一半的点 sp.stats.expon()#指数分布 sp.stats.norm.cdf()#累积分布函数 sp.st…

linux中和,|和||及分号(;)的用法

在linux中&#xff0c;我们经常会用到&和&&&#xff0c;|和||及分号(;)&#xff0c;但是好多人对其会混淆&#xff0c;不明白其中的意思&#xff0c;今天为大家讲解一下&和&&&#xff0c;|和||及分号(;)各自的说明和用法。 1.& & 表示程序…

【Cookie和Session】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 一、Cookie和Session&#xff08;面试常考&…

ChatGPT与讯飞星火实测对比

文章目录 一、推理测试测试提示词1&#xff1a;假设树上有10只鸟&#xff0c;开枪打死1只&#xff0c;那么树上还有几只鸟?- 测试提示词2&#xff1a;一艘船10天可以渡过太平洋&#xff0c;请计算10艘船多少天可以渡过太平洋。测试提示词3&#xff1a;我爸妈结婚的时候为什么不…

Qt - UI进阶

Qt - UI 进阶 布局控件及其坐标pos/position/scenePosition/globalPosition 场景和视图&#xff1f;&#xff1f;&#xff1f; 布局 https://blog.csdn.net/kongcheng253/article/details/128769765 控件及其坐标 pos/position/scenePosition/globalPosition pos()函数返回的…