JUC并发编程第三章——Java中的锁

1.Java中锁的常见面试题:

一、Synchronized 相关问题

Synchronized 用过吗,其原理是什么?


        在Java中,synchronized的底层原理是通过对象监视器(monitor)实现的。每个对象都有一个与之关联的监视器,也称为锁。当一个线程尝试进入一个被synchronized修饰的代码块或方法时,它会尝试获取对象的监视器(锁)。如果锁被其他线程持有,那么线程就会被阻塞,直到锁被释放。在Java虚拟机(JVM)中,每个对象的监视器在对象头中保存。对象头包含用于存储监视器信息的字段,以及其他对象元数据。JVM维护一个全局的监视器表,在表中记录每个对象的锁状态,包括被哪个线程持有、等待队列等信息。当线程尝试进入同步代码块时,JVM会检查对象的锁状态,如果锁未被持有,则线程可以获取锁并执行代码,同时在持有锁的线程中记录这个线程的信息。如果锁已被持有,则线程会被放到等待队列中等待锁被释放。通过对象监视器的机制,synchronized能够保证对共享资源的互斥访问,确保线程安全性。

你刚才提到获取对象的锁,这个"锁"到底是什么? 如何确定对象的锁?


对象锁的概念

在Java中,锁通常指的是同步机制中的一种状态,它用于控制多个线程对共享资源的访问。锁的本质是monitorentermonitorexit字节码指令的一个Reference类型的参数,即要锁定和解锁的对象。

如何确定对象的锁

确定对象的锁可以通过以下方式:

  1. 明确指定锁对象(同步代码块):如果Synchronized关键字明确指定了锁对象,例如Synchronized(变量名)Synchronized(this),那么加解锁的对象就是指定的那个对象。

  2. 非静态方法:如果Synchronized修饰的是非静态方法,那么此方法对应的对象实例就是锁对象。

  3. 静态方法:如果Synchronized修饰的是静态方法,那么此方法对应的类对象(Class对象)就是锁对象。

需要注意的是,当一个对象被锁住时,该对象内所有使用Synchronized修饰的方法都会被阻塞,而非Synchronized修饰的方法仍然可以正常被调用,不会受到锁的影响.


什么是可重入性,为什么说 Synchronized 是可重入锁?
JVM 对 Java 的原生锁做了哪些优化?
为什么说 Synchronized 是非公平锁?
什么是锁消除和锁粗化?

为什么说 Synchronized 是一个悲观锁?


Synchronized被称为悲观锁是因为它的策略是“先获取锁再进行操作”。在进入Synchronized代码块或方法时,线程会尝试获取锁,如果锁已被其他线程持有,则当前线程会被阻塞,直到获取到锁为止。这种机制是一种悲观的做法,它默认认为在并发情况下会发生竞争和冲突,因此需要通过获取锁来确保对共享资源的互斥访问。悲观锁的缺点在于当并发量较高时,线程之间会频繁竞争锁资源,导致线程阻塞和上下文切换的开销增加,降低了系统的并发性能。而且悲观锁会导致一些线程长时间等待获取锁,可能会出现死锁的情况。相对于悲观锁,乐观锁则是一种更加乐观的做法,它默认认为在并发情况下不会发生冲突,所以先进行操作,然后在提交时再进行冲突检测。乐观锁在一定程度上降低了锁的竞争和等待时间,提高了并发性能。常见的乐观锁实现包括基于CAS(Compare And Swap)的方式。

乐观锁的实现原理又是什么? 什么是 CAS ,它有什么优点?
乐观锁一定就是好的吗?


二、可重入锁 ReentrantLock 及其它显式锁相关问题

跟 Synchronized 相比,可重入锁 其实现原理有什么不同?
那么请谈谈 AQS 框架是怎么回事儿?
请尽可能详尽地对比下 Synchronized 和 ReentrantLock 的异同
ReentrantLock 是如何实现可重入性的?
三、其它

你怎么理解 Java 语言多线程的? 怎么处理并发? 线程池有那几个核心参数?
Java 加锁有哪儿种锁? 我先说 synchronized,刚讲到偏向锁,他就不让我讲了,太自信了
简单说说锁?
hashmap的实现原理? hash冲突怎么解决? 为什么使用红黑树?
spring 里面都使用了哪些设计模式? 循环依赖怎么解决?
项目中哪个地方用了 CountDownLatch,怎么使用的?

2.乐观锁和悲观锁的简单介绍

2.1 悲观锁

        认为自己在使用数据的时候一定有别的线程来修改数据,因此在获取数据的时候会先加锁,确保数据不会被别的线程修改.

synchronized和Lock的实现类都是悲观锁

适合写操作多的场景,先加锁可以保证写操作时数据正确,显式的锁定之后再操作同步资源

一句话定义:狼性锁

2.2 乐观锁

认为自己在使用数据的时候不会有别的线程修改数据或资源,所以不会添加锁

Java中使用无锁编程来实现,只是在更新的时候去判断,之前有没有别的线程更新了这个数据

如果这个数据没有被更新,当前线程将自己修改的数据成功写入
如果这个数据已经被其他线程更新,则根据不同的实现方式执行不同的操作,比如:放弃修改、重试抢锁等等
判断规则

版本号机制Version
最常采用的是CAS算法,Java原子类中的递增操作就通过CAS自旋实现的
适合读操作多的场景,不加锁的特性能够使其读操作的性能大幅提升

乐观锁则直接去操作同步资源,是一种无锁算法,得之我幸不得我命,再努力就是

一句话定义:佛系锁

2.3 乐观锁的实现方式

  1. 版本号机制:通过在数据表中增加一个版本号字段来实现。当读取数据时,将版本号一同读出,每次更新数据时,版本号加一。提交更新时,检查版本号是否一致,一致则更新并返回成功,不一致则表示数据已被其他事务修改,返回失败 。

  2. 时间戳机制:通过记录数据的时间戳来实现,每次更新数据时检查当前时间戳与记录的时间戳是否一致,一致则更新并返回成功,不一致则更新失败 。

  3. 原子操作:使用Atomic类(如AtomicInteger)或CAS(Compare-And-Swap)操作来实现,确保对共享资源的更新操作是原子性的 。

2.4 乐观锁的适用场景

乐观锁

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值