• java中锁的面试题


    1. synchronized锁(悲观锁、同步锁)

    • synchronized关键字:表示“同步”的。它可以对“多行代码”进行“同步”——将多行代码当成是一个完整的整体,一个线程如果进入到这个代码块中,会全部执行完毕,执行结束后,其它线程才会执行。这样可以保证这多行的代码作为完整的整体,被一个线程完整的执行完毕。

    • synchronized被称为“重量级的锁”方式,也是“悲观锁”——效率比较低。

    1.1synchronized有几种使用方式:

    • a).同步代码块【常用】
    • b).同步方法【常用】

    a**.同步代码块:**

    格式:
    synchronized(锁对象){

    }
    锁对象:
    1.语法上,可以是任意类的对象
    2.如果多条线程想要实现同步,那么这多条线程的锁对象必须一致

    b.同步方法:

    格式:
    修饰符 synchronized 返回值类型 方法名(形参列表){ }
    锁对象:
    非静态同步方法: 锁对象this
    静态同步方法:该方法所在类的字节码对象(类名.class)

    2.Lock锁

    Lock锁也称同步锁,加锁与释放锁方法化了,如下:

    • public void lock():加同步锁。

    • public void unlock():释放同步锁。

    面试题: sychronized和ReenteredLock区别?

    底层实现上来说

    synchronized 是JVM层面的锁,是Java关键字,通过monitor对象来完成(monitorenter与monitorexit),对象只有在同步块或同步方法中才能调用wait/notify方法,ReentrantLock 是从jdk1.5以来(java.util.concurrent.locks.Lock)提供的API层面的锁。

    synchronized 的实现涉及到锁的升级,具体为无锁、偏向锁、自旋锁、向OS申请重量级锁,

    ReentrantLock 实现则是通过利用CAS(CompareAndSwap)自旋机制保证线程操作的原子性和volatile保证数据可见性以实现锁的功能。

    是否可手动释放

    synchronized 不需要用户去手动释放锁,synchronized 代码执行完后系统会自动让线程释放对锁的占用; ReentrantLock则需要用户去手动释放锁,如果没有手动释放锁,就可能导致死锁现象。一般通过lock()和unlock()方法配合try/finally语句块来完成,使用释放更加灵活。

    是否可中断

    synchronized是不可中断类型的锁,除非加锁的代码中出现异常或正常执行完成; ReentrantLock则可以中断,可通过trylock(long timeout,TimeUnit unit)设置超时方法或者将lockInterruptibly()放到代码块中,调用interrupt方法进行中断。

    是否公平锁

    synchronized为非公平锁 ReentrantLock则即可以选公平锁也可以选非公平锁,通过构造方法new ReentrantLock时传入boolean值进行选择,为空默认false非公平锁,true为公平锁。

    3.volatile关键字

    volatile是一个"变量修饰符",它只能修饰"成员变量",它能强制线程每次从主内存获取值,并能保证此变量不会被编译器优化。

    • volatile能解决变量的可见性、有序性

    • volatile不能解决变量的原子性

    面试题 :能够说明volatile关键字和synchronized关键字的区别?

    1. volatile只能修饰成员变量,synchronized可以修饰代码块或者方法
    2. volatile是强制要求子线程每次使用共享变量都是重新从主内存中获取,synchronized实现的是互斥访问
    3. volatile只能解决可见性,有序性问题,不能解决原子性问题,但synchronize都可以解决

    3.死锁是什么?遇到死锁问该怎么解决?

    死锁:多个线程同时被阻塞,它们中的个或者全部都在等待某个资源被释放。由于线程被限期地阻塞,因此程序不可能正常终。

    (1)产生死锁的4个必要条件:

    1. 互斥条件:所谓互斥就是线程在某一个时间内独占资源
    2. 请求与保持条件:个线程因请求资源阻塞时,对已获得的资源保持不放。
    3. 不剥夺条件:线程已获得资源,在未使用完之前,不能强行剥夺。
    4. 循环等待条件:若线程之间形成种头尾相接的循环等待资源关系。

    (2)如何避免线程死锁?

    产死锁的四个必要条件,为了避免死锁,我们只要破坏产死锁的四个条件中的其中个就可以了。

    1. 破坏互斥条件 :这个条件我们没有办法破坏,因为我们锁本来就是想让他们互斥的(临界资源需要互斥访问)。
    2. 破坏请求与保持条件 :次性申请所有的资源。
    3. 破坏不剥夺条件 :占部分资源的线程进步申请其他资源时,如果申请不到,可以主动释放它占有的资源。
    4. 破坏循环等待条件 :靠按序申请资源来预防。按某顺序申请资源,释放资源则反序释放。破坏循环等待条件。

    避免死锁最简单的方法就是 阻止循环等待条件 ,将系统中所有的资源设置标志位、排序

    规定所有的进程申请资源必须以一定的顺序(升序或降序) 做操作来避免死锁。

    面试问题

    1. 乐观锁和悲观锁知道吗?

    2…乐观锁和悲观锁的优缺点和应用场景是什么?

  • 相关阅读:
    1000套web前端期末大作业 HTML+CSS+JavaScript网页设计实例 企业网站制作【建议收藏】
    esp32如何获得蓝牙地址
    (附源码)spring boot大学生就业质量调查分析系统 毕业设计 161457
    4、文件基础操作和缩放工具与抓手工具的使用
    lintcode 552 · 创建最大数 【算法 数组 贪心 hard】
    Pyspark图计算:GraphFrames的安装及其常用方法
    隔山打牛:金融大崩溃
    Keyboard, mouse and joystick
    【ASWC Arxml结构分解】-7-Explicit(显式)和Implicit(隐式) Sender-Receiver communication描述差异
    对西安交大轴承数据集XJTU-SY_Bearing_Datasets进行读取和处理:
  • 原文地址:https://blog.csdn.net/m0_67401270/article/details/125438744