Java面试-基础篇(一)6

synchronized与ReentrantLock的区别

说到synchronized与ReentrantLock,我们都知道,他们是java并发编程很重要的技术。他们可以帮助我们保证编程过程中数据的正确性,也就是我们常说的线程安全。

线程安全通常是多个线程在执行一段代码时采用锁机制实现的。

介绍锁机制前,先了解一下锁的分类。

从设计理念来分,有悲观锁和乐观锁。

悲观锁:认为每次拿数据时,别的线程都抢占修改,所以读写时,将数据进行锁定。

乐观锁:认为每次拿数据时,别的线程并不会抢占修改,所以拿数据处理时不上锁,处理完毕后,将处理完的数据写回内存时,进行判断,如果与预期一致则进行更新,不一致则更新失败。此处使用的时CAS(compare and swap)机制。

从锁的现象可分为公平锁和非公平锁

公平锁:某一线程释放资源后,按顺序唤醒下一个等待的线程,他们之间是排队的,有序的,每个线程都能获得执行的机会。在公平锁的情况下,它的好处是资源平均分配不会有线程饿死的情况。缺点是它的按顺序唤醒线程的开销过大,执行性能不高。

非公平锁:线程执行完毕后,接下来执行的线程进行抢占资源,谁抢到了,谁就执行,没有抢到的就滚去排队。他们之间是不排队的,无序的。每个线程获取执行的机会不相等,所以叫非公平锁。非公平锁的好处是执行效率高,谁抢到就谁用,不会按顺序唤醒线程,缺点是资源分配随机性强,可能会出现线程饿死的情况。

从锁的状态来分可分为偏向锁和重量级锁。

这3种锁其实是有关联的。偏向锁是某一线程持有锁时,等他用完锁以后再想用时,它在其他的线程中是优先级最高的,它可以一直持有锁。

而某一线程持有偏向锁,当其他线程来访问时获取不到锁,就会一直自旋,等待获取锁。此时偏向锁升级为了轻量级锁。

当线程一直获取不到锁,自旋一定的次数,线程就会阻塞。该锁就会升级为重量级锁。升级为重量级锁以后,当有线程再过来访问时,都会被阻塞,直到获取锁。

synchronized与ReentrantLock默认都是非公平锁,在java6以前,synchronized是重量级锁,所以那时候一般没人用。后来优化后好多了。

ReentrantLock可以通过修改配置修改为公平锁,但是synchronized就一直是非公平锁。

当使用 new ReentrantLock(true) 时,可以创建公平锁,如下源码所示:

 

 

 synchronized依赖于JVM,而ReentrantLock依赖于API,它是一个类,底层其实调用Lock接口,在此接口上做了实现,ReentrantLock需要显式的加锁和解锁。

1
public class ReentrantLock implements Lock, java.io.Serializable {private final Sync sync;/** * Base of synchronization control for this lock. Subclassed * into fair and nonfair versions below. Uses AQS state to * represent the number of holds on the lock. */abstract static class Sync extends AbstractQueuedSynchronizer {    private static final long serialVersionUID = -5179523762034025860L;    /**     * Performs {@link Lock#lock}. The main reason for subclassing     * is to allow fast path for nonfair version.     */    abstract void lock();}

  ReentrantLock相比较synchronized而言增加了一些功能。

  1. 等待可中断。ReentrantLock提供了一种能够钟断等待锁的线程机制,能够使等待的线程,先中断等待去做别的事情,使用Lock LockInterruptibly()实现
  2. 可实现公平锁。通过ReentrantLock类的ReentrantLock(boolean fair)构造方法实现
  3. 可选择性通知,唤醒线程(锁可以绑定多个条件)。该功能需要借助condition接口于new Condition()方法。而synchronized需要使用wait(),notify(),notifyAll()方法实现等待/通知的机制

 

posted @   行业小白  阅读(18)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示