Java基础--常见的几种锁

Updated on with 0 views and 0 comments

一、悲观锁和乐观锁

多线程访问共享资源时,会对共享资源有增删改查的操作;

悲观锁在线程操作共享资源期间,枷锁成功就会禁止其他线程操作共享资源;

乐观锁不限制各个线程对共享资源的操作,但是当线程要更新共享资源时,会先判断该资源有没有被其他线程修改,如果共享资源没有被其他线程更新,则更新共享资源,如果被其他资源更新,则根据自己的需求另作处理;

  • 悲观锁适合写操作较多的场景,加锁可以保证数据正确性,java的synchronized和Lock都是悲观锁实现
  • 乐观锁适合读操作较多的场景,不加锁可以提升性能,java的原子操作类就是基于乐观锁实现

二、自旋锁和非自旋锁

2.1 自旋锁

多线程获取共享资源时,若资源被其他线程占用,该线程就会等待获取锁资源,但是线程不会放弃已经拿到的CPU时间片,通过自旋等待共享资源被释放

2.2 非自旋锁

非自旋锁再等待其他线程施放锁的时候,会让出CPU时间片,使线程进入休眠,所释放后,才会重新获取CPU时间片

三、无锁、偏向锁、轻量级锁和重量级锁

偏向锁通过对比Mark Word处理加锁问题,避免执行CAS操作,轻量级锁通过CAS操作和自旋来解决加锁问题,避免线程阻塞和唤醒影响性能,重量级锁是将出了拥有锁的线程外,其他所有锁都阻塞。

  • 无锁 不对资源加锁,多个线程只有一个能修改资源,其他线程会重试
  • 偏向锁 同一个线程执行同步资源时自动获取资源
  • 轻量级锁 多个线程竞争同步资源时,没有获取到锁的线程会自旋等待锁释放
  • 重量级锁 多个线程竞争同步资源时,没有获取锁的线程会阻塞等待锁释放

具体参考java锁状态基本概念 - 问尤龙の时光 (wenyoulong.com)

四、公平锁和非公平锁

公平锁按照先来先服务原则,按照线程访问锁的先后顺序获取锁;

非公平锁则是多个线程抢占锁资源,谁拿到就是谁的;

  • 公平锁线程最终都会获取到锁资源,但是如果前面的线程占用所资源时间长,部分线程等待时间会较长,非公平锁部分线程可能会出现一致获取不到锁资源的情况
  • 公平锁出了获取到锁的线程之外,其他线程都会阻塞,CPU唤醒线程的开销比非公平锁大

ReentrantLock和synchronized默认都是非公平锁

五、可重入锁和不可重入锁

可重入锁就是一个线程的方法获取了锁,则该方法内部的调用的方法也可以获取到锁,ReentrantLock和synchronized都是可重入锁

不可重入锁就是外部方法中获取了一个锁,方法内部的另一个方法也需要获取锁,此时,就会一直等待外部方法施放锁,就会出现死锁的情况

六、排它锁和共享锁

排它锁一次只能被一个线程持有,JDK中的synchronized和JUC中Lock的实现类就是排它锁

共享锁可以被多个线程持有,获取了排它锁的线程只能读数据


标题:Java基础--常见的几种锁
作者:wenyl
地址:http://www.wenyoulong.com/articles/2023/06/21/1687318004633.html