锁面试题话术

1、介绍一下乐观锁和悲观锁

乐观锁的话就是比较乐观,每次去拿数据的时候,认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制或者CAS 算法实现。乐观锁在读操作比较多的场景比较适用,这样可以提高吞吐量,就像数据库提供的write_condition机制,其实都是乐观锁

悲观锁的话就是每次去拿数据的时候,也认为别人会修改数据,这个时候就会加上锁,这就导致其他线程想拿数据的话,就会阻塞,直到这个线程修改完成才会释放锁,让其他线程获取数据。在数据库里的行级锁、表级锁都是在操作之前就先锁住数据再操作数据 ,都属于悲观锁。Java中的 synchronized 和 ReentrantLock 等独占锁就是悲观锁思想的实现
Java中各种锁其实都是悲观锁的实现,在操作数据的时候,数据都会被当前线程锁住。

2、介绍一下公平锁和非公平锁

公平锁:指线程在等待获取同一个锁的时候,是严格按照申请锁的时间顺序来进行的,这就意味着在程序正常运行的时候,不会有线程执行不到的情况,但是也需要额外的机制来维护这种顺序,所以效率相对于非公平锁会差点

非公平锁:概念跟“公平锁”恰恰相反,随机线程获取锁,效率相对高,可能会导致某些线程一直获取不到CPU资源而执行不到

创建一个ReentrantLock默认就是非公平锁,当然也可以传入参数让他变成公平锁

new ReentrantLock(); //默认非公平锁 
new ReentrantLock(true); //公平锁

3、重入锁(递归锁)和不可重入锁(自旋锁)

//demo不用记忆,理解代码
public class Demo {
  private Lock lockA;//这是个锁
 
  public Demo(Lock Lock) {
    this.lockA = lock;
  }
 
  public void methodA() {//业务逻辑A
    lockA.lock();//获取锁,加锁
    methodB();//执行业务逻辑B
    lockA.unlock();//解锁
  }
 
  public void methodB() {//业务逻辑B
    lockA.lock();//同样获取锁,加锁操作
    //dosm
    lockA.unlock();//解锁
  }
  
}

重入锁:当我们运行methodA()的时候,线程获取了lockA,然后调用methodB()的时候发现也需要lockA,由于这是一个可重入锁,所以当前线程也是可以直接进入的。在java中,synchronized跟ReetrantLock都是可重入锁。
不可重入锁:methodA进入methodB的时候不能直接获取锁,必须先调用unLock释放锁。才能执行下去

4、共享锁和独占锁

java 并发包提供的加锁模式分为独占锁和共享锁。
独占锁:独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock 就是以独占方式实现的互斥锁。独占锁是一种悲观保守的加锁策略,它避免了线程之间读取数据发生冲突,如果某个只读线程获取锁,则其他读线程都只能等待

共享锁:共享锁则允许多个线程同时获取锁,并发访问 共享资源,比如说:ReadWriteLock。共享锁则是一种乐观锁,它放宽了加锁策略,允许多个执行读操作的线程同时访问共享资源。

5、synchronized和threadlocal的区别

synchronized关键字主要解决多线程共享数据的同步问题
ThreadLocal使用场合主要解决多线程中数据因并发产生不一致问题
ThreadLocal和Synchonized都用于解决多线程并发访问,但是ThreadLocal与synchronized有本质的区别: synchronized是利用锁的机制,使变量或代码块在某一时该只能被一个线程访问。而ThreadLocal是为每一个线程都提供了变量的副本,使得每个线程在某一时间访问到的并不是同一个对象,这样就隔离了多个线程对数据的数据共享。在使用完成后需要注意的是,需要把threadlocal里的数据移除。
而Synchronized却正好相反,它用于在多个线程间通信时能够获得数据共享。

6、ConcurrentHashMap如何实现线程安全

JDK1.7他的内部采用了的"分段锁"策略,ConcurrentHashMap的主干是个Segment数组。Segment 通过继承ReentrantLock 来进行加锁,所以每次需要加锁的操作锁住的是一个 segment,这样只要保证每个 Segment 是线程安全的,也就实现了全局的线程安全。一个Segment就是一个子哈希表,Segment里维护了一个HashEntry数组,默认有16 个 Segment,所以理论上,最多可以同时支持 16 个线程并发写,只要它们的操作分别分布在不同的 Segment 上。

  • 24
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值