Sychronized和ReentrantLock锁 面试题

2024-03-06 12:52

本文主要是介绍Sychronized和ReentrantLock锁 面试题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Sychronized和ReentrantLock锁 面试题

  • 前言
  • 1、Java死锁如何避免?
  • 2、公平锁和⾮公平锁的底层实现?
  • 3、ReentrantLock中tryLock()和lock()⽅法的区别?
  • 4、Sychronized的偏向锁、轻量级锁、重量级锁?
  • 5、谈谈你对AQS的理解,AQS如何实现可重⼊锁?
  • 6、AQS锁的类别?
  • 7、CountDownLatch和Semaphore的区别和底层原理?
  • 8、ReentrantLock底层原理?
  • 9、Sychronized和ReentrantLock的区别?
  • 10、Synchronized 偏向锁有个开关,如果默认开启有什么缺点?
  • 11、CAS与传统synchronized区别
  • 12、CAS是不是操作系统执行的?
  • 13、说一下CAS怎么用的,会有哪些问题?
  • 14、cas自增 和 Synchronized 自增 谁快?
  • 15、Synchronized 和 ReentracLock 哪个快,为啥?
  • 16、怎么检测一个线程是否拥有锁?
  • 17、事务未提交而锁提前释放了?
  • 18、AtomicInteger计数器自增到一万以后,怎么归零?
  • GIT
  • 19、什么是git?
  • 20、列举工作中常用的git命令:
  • 总结


前言

最新的 Java 面试题,技术栈涉及 Java 基础、集合、多线程、Mysql、分布式、Spring全家桶、MyBatis、Dubbo、缓存、消息队列、Linux…等等,会持续更新。

如果对老铁有帮助,帮忙免费点个赞,谢谢你的发财手!

1、Java死锁如何避免?

造成死锁的4个必要条件:

  • 1.⼀个线程每次只能占有⼀个资源;
  • 2.⼀个线程在阻塞等待某个资源时,不释放已占有资源;
  • 3.⼀个线程已占有的资源,在未使⽤完之前,不能被强⾏剥夺;
  • 4.多个线程形成循环等待的关系。
    如果要避免死锁,只需要其中某⼀个条件不满⾜即可。
    在开发过程中:
  • 1.要注意加锁顺序,保证每个线程按同样的顺序进⾏加锁解锁;
  • 2.要注意加锁时限,可以针对锁设置⼀个超时时间;
  • 3.要注意死锁检查,这是⼀种预防机制,确保在第⼀时间发现死锁并进⾏解决。

2、公平锁和⾮公平锁的底层实现?

公平锁和⾮公平锁,它们的底层实现都会使⽤AQS来进⾏排队。
它们的区别在于:

  • 如果是公平锁,会先检查AQS队列中是否存在线程在排队,如果有线程在排队,则当前线程也进⾏排队。
  • 如果是⾮公平锁,则不会去AQS队列中检查是否有线程在排队,⽽是直接竞争锁。
    不管是公平锁还是⾮公平锁,⼀旦没竞争到锁,都会进⾏排队,当锁释放时,都是唤醒排在最前⾯的线程,所以⾮公平锁只是体现在了线程加锁阶段,而没有体现在线程唤醒阶段。
    另外,不管是公平锁还是⾮公平锁都是可重⼊的。

3、ReentrantLock中tryLock()和lock()⽅法的区别?

  • 1.tryLock()表示尝试加锁,可能加到,也可能加不到,该⽅法不会阻塞线程,如果加到锁则返回true,没有加到则返回false ;
  • 2.lock()表示阻塞加锁,线程会阻塞直到加到锁,⽅法也没有返回值。

4、Sychronized的偏向锁、轻量级锁、重量级锁?

  • 1、偏向锁:在锁对象的对象头中记录了当前获取到锁的线程ID,如果该线程⼜来获取锁,就可以直接获取到了,这就是可重入的概念;
  • 2、轻量级锁:如果有另外的线程来竞争锁,偏向锁就会升级为轻量级锁,轻量级锁的底层是通过⾃旋来实现的,并不会阻塞线程;
  • 3、重量级锁:如果⾃旋次数超过10次仍然没有获取到锁,则会升级为重量级锁,重量级锁会导致线程阻塞。
  • 4、⾃旋锁:⾃旋就是线程在获取锁的过程中,不会去阻塞线程,是线程通过CAS获取预期的⼀个标记,如果没有获取到,则继续循环获取,如果获取到了则表示获取到了锁,这个过程线程⼀直在运⾏中,消耗的CPU资源比较少,⽐较轻量。

5、谈谈你对AQS的理解,AQS如何实现可重⼊锁?

  • 1.AQS是⼀个抽象的对列同步器,在AQS中,维护了一个volatile修饰的state标识和⼀个双向链表队列(FIFO);
  • 2.这个队列就是⽤来给线程排队的,⽽state就像是⼀个红绿灯,⽤来控制线程排队或者放⾏的;
  • 3.在可重⼊锁的场景下,state就⽤来表示加锁的次数,0标识⽆锁,每加⼀次锁,state就加1,释放锁state就减1。

6、AQS锁的类别?

AQS分为“排他锁”和“共享锁”两种:

  • 1.排他锁:是指在同一时刻只能有一个线程去占有锁,其他线程既不可以读,也不可以写,比如ReentrantLock;
  • 2.共享锁:是指在同一时刻可以有多个线程去占有锁,其他线程可以读,但不可以写,比如CountDownLatch计数器和Semaphore信号量;
    另外AQS也支持同时实现独占和共享两种方式,比如ReentrantReadWriteLock。

7、CountDownLatch和Semaphore的区别和底层原理?

底层都是通过AQS实现的。

  • CountDownLatch计数器:比如某个任务分为N个子线程并发去执行,state 也初始化为N;每个子线程执行完后调用countDown方法,state会减1,当所有子线程都执行完后,即state=0 ,然后会依次去唤醒AQS中排队的线程。
  • Semaphore信号量:我们常常用它来控制对有限资源的访问,每次使用资源前,先申请一个信号量,如果信号量不够,就会阻塞等待,并通过AQS来排队,当某个线程释放资源后,就释放一个信号量,然后会依次去唤醒AQS中排队的线程。

8、ReentrantLock底层原理?

底层是通过AQS实现的,state 初始化为 0,表示无锁状态;A 线程调用lock(加锁) 时,会将 state加 1 ,直到 A 线程调用 unlock(释放锁) 到 state=0为止,其它线程才有机会获取该锁。当然,释放锁之前,A 线程自己是可以重复获取该锁的,state 会累加,这就是可重入的概念。但要注意,加了多少次就锁要释放多少次,这样才能保证state恢复到0。

9、Sychronized和ReentrantLock的区别?

  • 1、Sychronized是⼀个关键字,ReentrantLock是⼀个类;
  • 2、Sychronized会自动的加锁和释放锁,ReentrantLock需要手动加锁和释放锁;
  • 3、Sychronized是非公平锁,ReentrantLock可以选择公平锁或非公平锁(默认);
  • 4、Sychronized是JVM层⾯的锁,ReentrantLock是API层⾯的锁。
  • 5、ReentrantLock有个tryLock()方法,尝试抢占锁,不会造成阻塞,加到锁返回true。
    理解第4点:Sychronized锁的是对象,锁信息保存在JVM对象头中,ReentrantLock是通过AQS中一个volatile修饰的state 来标识锁的状态。

10、Synchronized 偏向锁有个开关,如果默认开启有什么缺点?

JDK15默认关闭偏向锁优化,如果要开启可以使用XX:+UseBiasedLocking,但使用偏向锁相关的参数都会触发deprecate警告。
原因:在现在的jdk中,偏向锁加锁时 带来的性能提升 从整体上看并没有过多的收益,但撤销锁的成本过高,需要在一个安全点停止拥有锁的线程,使其变成无锁状态。

11、CAS与传统synchronized区别

CAS工作原理是基于乐观锁且操作是原子性的,与synchronized的悲观锁(底层需要调用操作系统的mutex锁)相比,效率也会相对高一些。

12、CAS是不是操作系统执行的?

不是,CAS是主要是通过处理器的指令来保证原子性的 。

13、说一下CAS怎么用的,会有哪些问题?

CAS就是我们所说的比较和交换,是采用的乐观锁技术,来实现线程安全的问题。
CAS有三个属性:旧值(A)、新值(B)、内存对象(V);
CAS原理就是对V进行赋值时,先判断原来的值是否为A,如果为A,就把新值B赋值到V,如果原来的值不是A(代表V的值放生了变化),那么会通过循环再走CAS流程,直到能够把新值B赋值成功(会给CPU带来很大的开销)。
CAS会有ABA的问题,可以通过加版本号,更新的时候时候不仅比较值,还比较版本号。

14、cas自增 和 Synchronized 自增 谁快?

  • 1、在线程数较少的时候,CAS实现比较快,性能优于synchronized,因为synchronized是悲观锁,存在锁竞争,会造成阻塞。
  • 2、当线程数大于一定数量的时候,CAS性能就不如synchronized了,因为多个线程在循环调用CAS接口,虽然不会让其他线程阻塞,但是这个时候竞争激烈,会导致CPU到达100%,同时会消耗更多时间。

15、Synchronized 和 ReentracLock 哪个快,为啥?

Synchronized 底层实现由JVM保证:在JVM运行过程中,可能出现偏向锁,轻量级锁,重量级锁。

  • 偏向锁:当线程第一次获取到锁的时候,将对象头中的 mark word 中的偏向锁线程的标识设为自己的id,当有其他线程竞争锁的时候,发现偏向锁线程的标识并不是自己,会进行一次 CAS替换,如果不成功,就会将锁升级为轻量级锁(消耗极少);
  • 轻量级锁:当前线程会将对象头中的 mark Word 复制到自己的栈空间中,然后通过自旋来获取锁,自旋10次还是获取锁失败,说明当前锁存在竞争,会将对象头的锁标识改为重量级指针,锁会膨胀为重量级锁(消耗:复制和自旋);
  • 重量级锁:需要操作系统实现线程之间的切换,这就需要从用户态转换到内核态,这个成本非常高,状态之间的转换需要相对比较长的时间。
  • ReentrantLock 底层是基于 AQS 实现:AQS 内部维护了一个volatile修饰的state标识以及⼀个双向链表队列(FIFO),volatile 消耗小于 Synchronized 。
    因此性能比较:偏向锁 > 轻量级锁 > ReentrantLock > Synchronized。

16、怎么检测一个线程是否拥有锁?

在 java.lang.Thread 中有一个 holdsLock()方法,拥有锁会返回 true 。

17、事务未提交而锁提前释放了?

高并发情况下,数据库事务未提交,但是锁已经释放。

  • 1、把整个事务单独封装成一个方法, 放在锁的工作范围之内;
  • 2、手动提交事务,因为事务是方法结束后才提交,我们可以手动提交事务;
  • 3、采用的Redisson可重入锁,提供watchdog机制,在锁释放前默认每10s重置锁失效时间为30s。

18、AtomicInteger计数器自增到一万以后,怎么归零?

volatile仅仅保证变量在线程间保持可见性,却依然不能保证非原子性的操作,还是用AtomicInteger类。
使用AtomicInteger.set(0)或.getAndSet(0)。

GIT

19、什么是git?

Git是一款开源的分布式版本控制系统。

20、列举工作中常用的git命令:

  • 将项目下载至本地:git clone http://xxx.git;
  • 提交文件:git commit -m “修复bug”;
  • 多次提交合成一次提交:git rebase -i HEAD~n;
  • 推送代码:git push origin dev;
  • 拉取并合并代码:git pull origin dev 等价于 git fetch origin dev + git merge origin/dev;
  • 查看历史记录:git log ;
  • 撤回(回退)版本:git revert(reset --hard) 提交id;
  • 创建并切换分支:git checkout -b dev 等价于git branch dev + git checkout dev;
  • 查看本地(远程/所有)分支:git branch(-r/-a);
  • 备份(恢复)当前工作区的内容:git stash(pop)

总结

都已经看到这里啦,赶紧收藏起来,祝您工作顺心,生活愉快!

这篇关于Sychronized和ReentrantLock锁 面试题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/780121

相关文章

荣耀嵌入式面试题及参考答案

在项目中是否有使用过实时操作系统? 在我参与的项目中,有使用过实时操作系统。实时操作系统(RTOS)在对时间要求严格的应用场景中具有重要作用。我曾参与的一个工业自动化控制项目就采用了实时操作系统。在这个项目中,需要对多个传感器的数据进行实时采集和处理,并根据采集到的数据及时控制执行机构的动作。实时操作系统能够提供确定性的响应时间,确保关键任务在规定的时间内完成。 使用实时操作系统的

一些其他面试题

阿里二面:那你来说说定时任务?单机、分布式、调度框架下的定时任务实现是怎么完成的?懵了。。_哔哩哔哩_bilibili 1.定时算法 累加,第二层每一个格子是第一层的总时间400 ms= 20 * 20ms 2.MQ消息丢失 阿里二面:高并发场景下引进消息队列有什么问题?如何保证消息只被消费一次?真是捏了一把汗。。_哔哩哔哩_bilibili 发送消息失败

zookeeper相关面试题

zk的数据同步原理?zk的集群会出现脑裂的问题吗?zk的watch机制实现原理?zk是如何保证一致性的?zk的快速选举leader原理?zk的典型应用场景zk中一个客户端修改了数据之后,其他客户端能够马上获取到最新的数据吗?zk对事物的支持? 1. zk的数据同步原理? zk的数据同步过程中,通过以下三个参数来选择对应的数据同步方式 peerLastZxid:Learner服务器(Follo

java常用面试题-基础知识分享

什么是Java? Java是一种高级编程语言,旨在提供跨平台的解决方案。它是一种面向对象的语言,具有简单、结构化、可移植、可靠、安全等特点。 Java的主要特点是什么? Java的主要特点包括: 简单性:Java的语法相对简单,易于学习和使用。面向对象:Java是一种完全面向对象的语言,支持封装、继承和多态。跨平台性:Java的程序可以在不同的操作系统上运行,称为"Write once,

【Kubernetes】常见面试题汇总(三)

目录 9.简述 Kubernetes 的缺点或当前的不足之处? 10.简述 Kubernetes 相关基础概念? 9.简述 Kubernetes 的缺点或当前的不足之处? Kubernetes 当前存在的缺点(不足)如下: ① 安装过程和配置相对困难复杂; ② 管理服务相对繁琐; ③ 运行和编译需要很多时间; ④ 它比其他替代品更昂贵; ⑤ 对于简单的应用程序来说,可能不

【附答案】C/C++ 最常见50道面试题

文章目录 面试题 1:深入探讨变量的声明与定义的区别面试题 2:编写比较“零值”的`if`语句面试题 3:深入理解`sizeof`与`strlen`的差异面试题 4:解析C与C++中`static`关键字的不同用途面试题 5:比较C语言的`malloc`与C++的`new`面试题 6:实现一个“标准”的`MIN`宏面试题 7:指针是否可以是`volatile`面试题 8:探讨`a`和`&a`

Laravel 面试题

PHP模块 PHP7 和 PHP5 的区别,具体多了哪些新特性? 性能提升了两倍 结合比较运算符 (<=>) 标量类型声明 返回类型声明 try…catch 增加多条件判断,更多 Error 错误可以进行异常处理 匿名类,现在支持通过new class 来实例化一个匿名类,这可以用来替代一些“用后即焚”的完整类定义 …… 了解更多查看文章底部链接 PHP7 新特性 为什么 PHP

【吊打面试官系列-Redis面试题】说说 Redis 哈希槽的概念?

大家好,我是锋哥。今天分享关于 【说说 Redis 哈希槽的概念?】面试题,希望对大家有帮助; 说说 Redis 哈希槽的概念? Redis 集群没有使用一致性 hash,而是引入了哈希槽的概念,Redis 集群有 16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点负责一部分 hash 槽。

【Kubernetes】常见面试题汇总(一)

目录 1.简述 etcd 及其特点? 2.简述 etcd 适应的场景? 3.简述什么是Kubernetes? 4.简述 Kubernetes和 Docker的关系? 1.简述 etcd 及其特点? (1)etcd 是Core0s 团队发起的开源项目,是一个管理配置信息和服务发现(service discovery)的项目,它的目标是构建一个高可用的分布式键值(keyvalue)数据

2018秋招C/C++面试题总结

博主从8月中旬开始大大小小面试了十几家公司,至今也许是告一段落吧,希望后面会有好结果,因此总结记录一些C/C++方向常见的问题。和大家一起学习! 参考了互联网的各种资源,自己尝试归类整理,谢谢~ 一、C和C++的区别是什么? C是面向过程的语言,C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛。 C中函数不能进行重载,C++函数可以重载 C++在C的基础上增添类,C是一个结构