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..乐观锁和悲观锁的优缺点和应用场景是什么?

版权声明:程序员胖胖胖虎阿 发表于 2022年9月12日 上午12:24。
转载请注明:java中锁的面试题 | 胖虎的工具箱-编程导航

相关文章

暂无评论

暂无评论...