Java面试题冲刺第二十四天--并发编程

这篇文章主要为大家分享了最有价值的三道关于数据库的面试题,涵盖内容全面,包括数据结构和算法相关的题目、经典面试编程题等,感兴趣的小伙伴们可以参考一下

面试题1:说一下你对ReentrantLock的理解?

ReentrantLock是JDK1.5引入的,它拥有与synchronized相同的并发性和内存语义,并提供了超出synchonized的其他高级功能(例如,中断锁等候、条件变量等),并且使用ReentrantLock比synchronized能获得更好的可伸缩性。

ReentrantLock主要利用: CAS(compare-and-swap) + AQS(AbstractQueuedSynchronizer)队列来实现。它支持公平锁和非公平锁,两者的实现类似。

CAS:

CAS(compare-and-swap),见名知意,比较并交换。CAS 加 volatile 关键字是实现并发包的基石。没有CAS就不会有并发包,synchronized是一种独占锁、悲观锁,java.util.concurrent中借助了CAS指令实现了一种区别于synchronized的一种乐观锁。

CAS引用了乐观锁思想,每次拿数据的时候都认为别的线程不会修改这个数据,所以不会上锁,但是在更新的时候会通过标记参数判断一下在此期间(更新期间)别的线程有没有已经修改过该标记数据,如果发现有其他线程在修改且未修改完成,并不会像悲观锁那样阻塞线程,而是直接返回,可以去选择再次重试获得锁,也可以直接退出。

举个流程示例

如CAS操作包括三个操作数:需要读写的内存位置(V)、预期原值(A)、新值(B)。如果内存位置与预期原值的A相匹配,说明在此期间(更新期间)别的线程未修改过该标记数据,那么将内存位置的值更新为新值B。如果内存位置与预期原值的值不匹配,那么处理器不会做任何操作。

无论哪种情况,它都会在 CAS 指令之前返回该位置的值。(在 CAS 的一些特殊情况下将仅返回 CAS 是否成功,而不提取当前值。)

AQS:

AQS主要利用硬件原语指令CAS,来实现轻量级多线程同步机制,并且不会引起CPU上文切换和调度,同时提供内存可见性和原子化更新保证(线程安全的三要素:原子性、可见性、顺序性)。

AQS的本质上是一个同步器/阻塞锁的基础框架,其作用主要是提供加锁、释放锁,并在内部维护一个FIFO等待队列,用于存储由于锁竞争而阻塞的线程。

追问1:你认为 ReentrantLock 相比 synchronized 都有哪些区别?

优秀问答摘自:https://ask.csdn.net/questions/1101634

两者的共同点:

  • 都是用来协调多线程对共享对象、变量的访问
  • 都是可重入锁,同一线程可以多次获得同一个锁
  • 都保证了可见性和互斥性

两者的不同点:

  • ReentrantLock 显示的获得、释放锁,synchronized 隐式获得释放锁;
  • ReentrantLock 可响应中断、可轮回,synchronized 是不可以响应中断的,为处理锁的不可用性提供了更高的灵活性;
  • ReentrantLock 是API 级别的,synchronized 是 JVM 级别的;
  • ReentrantLock 可以实现公平锁;
  • ReentrantLock 通过 Condition 可以绑定多个条件;
  • 底层实现不一样, synchronized 是同步阻塞,使用的是悲观并发策略,ReentrantLock 是同步非阻塞,采用的是乐观并发策略;
  • Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言实现;
  • synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;
  • 而 Lock 在发生异常时,如果没有主动通过 unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁。
 Lock lock = new ReentrantLock(); Condition condition = lock.newCondition(); lock.lock(); try { while(条件判断表达式) { condition.wait(); } // 处理逻辑 } finally { lock.unlock(); } 
  • Lock 可以让等待锁的线程响应中断,而 synchronized 却不行,使用 synchronized 时,等待的线程会一直等待下去,不能够响应中断。
  • 通过 Lock 可以知道有没有成功获取锁,而 synchronized 却无法办到。
  • Lock 可以提高多个线程进行读操作的效率,就是实现读写锁等。

面试题2:解释一下公平锁和非公平锁?

ReenTrantLock可以指定是公平锁还是非公平锁,而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获锁。

我们刚才提及到AQS中,如果线程A正处于lock状态,线程B进来时发现线程A处于lock状态,会自动进入阻塞队列,等待取锁;这时候当线程C也进来了也发现线程A处于lock状态,也会自动进入阻塞队列。那么等A释放锁后,下次加锁到底是线程B先拿到还是线程C先拿到呢?

在这里插入图片描述

ReentrantLock有个构造方法用于设置锁的公平性,如果我们仅仅是new了一个ReentrantLock的话,那么就是非公平锁(默认),就是靠自己去争取,完全的随机性。如果我们在new ReentrantLock(true) 加入 true参数时,公平锁,就会遵循先入先出的原则,保证了锁的公平性。

面试题3:能详细说一下CAS具体实现原理么?

首先,CAS的英文单词是Compare and Swap,即是比较并替换。CAS机制中使用了3个基本操作数:内存地址V,旧的预期值A,待替换的新值B。

CAS规则是:当需要更新一个变量的值的时候,只有当变量的预期值A和内存地址V中的实际值相同的时候,才会把内存地址V对应的值替换成B。

下面我们通过一个例子来讲解:

1.在内存地址V中存储的值是陈哈哈

在这里插入图片描述

2.线程01想要把变量的值改成侨总,对于线程01而言,内存地址 V=‘陈哈哈',旧的预期值 A=‘陈哈哈',需要替换的新值 B=‘侨总'。

在这里插入图片描述

3.在线程01要提交更新之前,另外一个线程02抢先一步,将内存地址V中的值更新成了V='比特币'。

在这里插入图片描述

4.线程01开始提交更新的时候,按照CAS机制,首先进行A的值与内存地址V中的值进行比较( A=‘陈哈哈' V=‘比特币'),发现 A != V 中的实际值,提交失败。

在这里插入图片描述

5.线程01未获取锁后进行重试,重新获取内存

以上就是Java面试题冲刺第二十四天--并发编程的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » Java