ToB企服应用市场:ToB评测及商务社交产业平台

标题: 阿里二面:Java中锁的分类有哪些?你能说全吗? [打印本页]

作者: 道家人    时间: 2024-5-15 07:17
标题: 阿里二面:Java中锁的分类有哪些?你能说全吗?
引言

在多线程并发编程场景中,锁作为一种至关重要的同步工具,承担着和谐多个线程对共享资源访问秩序的任务。其核心作用在于确保在特定时间段内,仅有一个线程能够对资源进行访问或修改操纵,从而有用地保护数据的完整性和一致性。锁作为一种底层的安全构件,有力地防止了竞态条件和数据不一致性的题目,尤其在涉及多线程或多历程共享数据的复杂场景中显得尤为关键。
而了解锁的分类,能资助我们何种业务场景下利用选择哪种锁。

基于锁的获取与开释方式分类

计划于所得获取与开释方式进行分类,Java中的锁可以分为:显式锁和隐式锁。
隐式锁

Java中的隐式锁(也称为内置锁或自动锁)是通过利用synchronized关键字实现的一种线程同步机制。当一个线程进入被synchronized修饰的方法或代码块时,它会自动得到对象级别的锁,退出该方法或代码块时则会自动开释这把锁。
在Java中,隐式锁的实现机制主要包罗以下两种类型:
长处:
缺点:
适用场景: 隐式锁适用于相对简单的多线程同步需求,尤其是在只需要保护某个对象状态完整性,且无需过多关注锁策略灵活性的场合。对于要求更高并发性和更复杂锁管理逻辑的应用场景,显示锁通常是一个更好的选择。
显式锁

显式锁是由java.util.concurrent.locks.Lock接口及其诸多实现类提供的同步机制,相较于通过synchronized关键字实现的隐式锁机制,显式锁赋予开辟者更为精细和灵活的控制能力,使其能够在多线程情况中精准掌控同步动作。显式锁的核心作用在于确保在任何时刻仅有一个线程能够访问关键代码段或共享数据,从而有用防止数据不一致性题目和竞态条件。
相较于隐式锁,显式锁提供了更为多样化的锁操纵选项,包罗但不限于支持线程在等待锁时可被中断、根据先后顺序分配锁资源的公平锁与非公平锁机制,以及能够设定锁获取等待时间的定时锁功能。这些特性共同增强了显式锁在面对复杂并发场景时的适应性和可调控性,使之成为解决高度定制化同步需求的理想工具。
日常开辟中,常见的显式锁分类有如下几种:
长处:
缺点:
基于对资源的访问权限

按照线程对资源的访问权限来分类,可以将锁分为:独占锁(Exclusive Lock)和共享锁(Shared Lock)。
独占锁

独占锁(Exclusive Lock),又称排他锁或写锁,是一种同步机制,它确保在任一时刻,最多只有一个线程可以得到锁并对受保护的资源进行访问或修改。一旦线程得到了独占锁,其他全部试图获取同一锁的线程将被阻塞,直到拥有锁的线程开释锁为止。独占锁主要用于保护那些在并发情况下会被多个线程修改的共享资源,确保在修改期间不会有其他线程干扰,从而维护数据的一致性和完整性。
对于独占锁就像图书馆里的某本书,这本书只有唯一的一本。当一个读者想要借阅这本书时,他会去图书管理员那里登记并拿到一个“借书凭证”(相称于独占锁)。此时,这本书就被锁定了,其他读者无法借阅这本书,直至第一个读者归还册本并交回“借书凭证”。这就像是线程得到了独占锁,只有拥有锁的线程可以修改或操纵资源(册本),其他线程必须等待锁的开释才能实行相应的操纵。
而独占锁的实现方式,主要有如下两种:
长处:
缺点:
共享锁

共享锁(Shared Lock)也称为读锁(Read Lock),是一种多线程或多历程并发控制的同步机制,它允许多个线程同时读取共享资源,但不允许任何线程修改资源。在数据库系统和并发编程中广泛利用,确保在并发读取场景下数据的一致性。
共享锁就像图书馆里有一套多人阅读的杂志合订本,这套合订本可以被多个读者同时翻阅,但是任何人都不能带走或在上面做标记。当一个读者要阅读时,他会向图书管理员申请“阅读凭证”(相称于共享锁)。如果有多个读者想阅读,图书管理员会给他们每人一份阅读凭证,如许各人都可以坐在阅览室里一起阅读这套合订本,但是都不能单独占有或改变它。在并发编程中,多个线程可以同时获取共享锁进行读取操纵,但都不能修改数据,这就像是多个线程同时持有共享锁读取资源,但不允许在此期间进行写操纵。
实现共享锁的关键机制是读写锁(ReadWriteLock),这是一种特殊类型的共享锁机制,它巧妙地将对共享资源的访问权限划分为了读取权限和写入权限两类。在读写锁的控制下,多个线程可以同时进行对共享数据的读取操纵,形成并发读取,而对数据的写入操纵则接纳独占式处理,确保同一时间段内仅有一个线程实行写入操纵。在写入操纵正在进行时,无论是其他的读取操纵还是写入操纵都会被暂时阻塞,直至写操纵竣事。
读写锁包含两种锁模式:读锁(ReadLock) 和 写锁(WriteLock)。当多个线程需要访问同一份共享数据时,只要这些线程都是进行读取操纵,则都能成功获取并持有读锁,从而实现并行读取。然而,一旦有线程尝试进行写入操纵,那么不论是其他正在实行读取的线程还是准备进行写入的线程,都无法继续获取读锁或写锁,直至当前写操纵全部完成并开释写锁。如许,读写锁有用地平衡了读取密集型任务的并发性和写入操纵的原子性要求。
长处:
缺点:
如以下利用共享锁示例:
  1. public class SharedResource {
  2.     private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
  3.     private final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
  4.     private final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
  5.     private int data;
  6.     public void modifyData(int newData) {
  7.         // 获取写锁(独占锁),在同一时刻只有一个线程可以获取写锁
  8.         writeLock.lock();
  9.         System.out.println(Thread.currentThread().getName() + " Modify Data");
  10.         try {
  11.             // 修改数据
  12.             this.data = newData;
  13.             // 数据修改相关操作...
  14.         } finally {
  15.             // 无论如何都要确保解锁
  16.             writeLock.unlock();
  17.         }
  18.     }
  19.     public int readData() {
  20.         // 获取读锁(共享锁),允许多个线程同时获取读锁进行读取操作
  21.         readLock.lock();
  22.         System.out.println(Thread.currentThread().getName() + " Read Data");
  23.         try {
  24.             // 读取数据,此时其他读取线程也可以同时读取,但不允许写入
  25.             return this.data;
  26.         }finally {
  27.             // 释放读锁
  28.             readLock.unlock();
  29.         }
  30.     }
  31.     public static void main(String[] args) {
  32.         SharedResource resource = new SharedResource();
  33.         Thread reader1 = new Thread(() -> System.out.println("Reader 1 reads: " + resource.readData()), "Reader1");
  34.         Thread reader2 = new Thread(() -> System.out.println("Reader 2 reads: " + resource.readData()), "Reader1");
  35.         Thread writer = new Thread(() -> resource.modifyData(42), "Writer1");
  36.         reader1.start();
  37.         reader2.start();
  38.         writer.start();
  39.         // 等待所有线程执行完成
  40.         try {
  41.             reader1.join();
  42.             reader2.join();
  43.             writer.join();
  44.         } catch (InterruptedException e) {
  45.             e.printStackTrace();
  46.         }
  47.     }
  48. }
复制代码
打印结果:

在这个示例中,利用了 ReentrantReadWriteLock 来控制对 data 的读写操纵。readData() 方法利用读锁,允许多个线程同时读取数据,而 modifyData() 方法利用写锁,确保同一时间只有一个线程可以修改数据。如许就可以在并发场景下既保证数据读取的并发性,又制止了数据因并发写入而造成的不一致性题目。
基于锁的占有权是否可重入

按照锁的占有权是否可以重入,可以把锁分为:可重入锁以及不可重入锁。
可重入锁

可重入锁(Reentrant Lock)作为一种线程同步机制,具备独特的重入特性,即当线程已经获取了锁后,它可以再次哀求并成功得到同一把锁,从而制止了在递归调用或嵌套同步块中产生的死锁风险。这意味着在实行锁保护的代码区域时,即便调用了其他同样被该锁保护的方法或代码片断,持有锁的线程也能顺利完成操纵。
在多线程情况下,可重入锁饰演着至关重要的角色,它严格限定了同一时间只能有一个线程访问特定的临界区,有用防止了并发访问引发的数据不一致和竞态条件题目。此外,通过允许线程在持有锁的状态下重新获取该锁,可重入锁巧妙地解决了同类锁之间由于互相称待而形成的潜在死锁状况,从而提升了多线程同步的安全性和可靠性。
可重入锁主要可以通过以下三种方式实现:
长处:
缺点:
以下为可重入锁利用示例:
  1. public class ReentrantLockExample {
  2.     private final Lock lock = new ReentrantLock();
  3.     // 假设这是一个需要同步访问的共享资源
  4.     private int sharedResource;
  5.     public void increment() {
  6.         // 获取锁
  7.         lock.lock();
  8.         try {
  9.             // 在锁保护下执行操作
  10.             sharedResource++;
  11.             // 这里假设有个内部方法也需要同步访问sharedResource
  12.             doSomeOtherWork();
  13.         } finally {
  14.             // 无论发生什么情况,最后都要释放锁
  15.             lock.unlock();
  16.         }
  17.     }
  18.     // 可重入的内部方法
  19.     private void doSomeOtherWork() {
  20.         // 因为当前线程已经持有锁,所以可以再次获取
  21.         lock.lock();
  22.         try {
  23.             // 执行依赖于sharedResource的操作
  24.             sharedResource -= 1;
  25.             System.out.println("Inner method executed with sharedResource: " + sharedResource);
  26.         } finally {
  27.             // 释放锁
  28.             lock.unlock();
  29.         }
  30.     }
  31.     public static void main(String[] args) {
  32.         ReentrantLockExample example = new ReentrantLockExample();
  33.         Thread thread1 = new Thread(example::increment);
  34.         Thread thread2 = new Thread(example::increment);
  35.         thread1.start();
  36.         thread2.start();
  37.         // 等待两个线程执行完毕
  38.         try {
  39.             thread1.join();
  40.             thread2.join();
  41.         } catch (InterruptedException e) {
  42.             e.printStackTrace();
  43.         }
  44.         // 输出最终的sharedResource值
  45.         System.out.println("Final sharedResource value: " + example.sharedResource);
  46.     }
  47. }
复制代码

示例中,increment()方法和内部的doSomeOtherWork()方法都需要在获取锁的情况下实行。由于ReentrantLock是可重入的,以是在increment()方法内部调用doSomeOtherWork()时,线程仍然可以成功获取锁,并继续实行操纵。当全部操纵完成时,通过finally块确保了锁的开释。如允许以制止死锁,并确保在多线程情况下对共享资源的访问是线程安全的。
不可重入锁

不可重入锁(Non-reentrant Lock)是一种线程同步机制,它的核心特征在于克制同一个线程在已经持有锁的前提下再度获取相同的锁。若一个线程已取得不可重入锁,在实在行路径中遇到需要再次获取该锁的场景时,该线程将会被迫等待,直至原先获取的锁被开释,其他线程才有可能获取并实行相关临界区代码。
此类锁机制同样服务于多线程情况下的资源共享保护,旨在确保同一时间内仅有单一线程能够访问临界资源,从而有用规避数据不一致性和竞态条件等题目。相较于可重入锁,不可重入锁在递归调用或涉及锁嵌套的复杂同步场景下表现出局限性,因其可能导致线程阻塞和潜在的死锁风险,降低了线程同步的灵活性和安全性。在实际开辟中,除非有特殊的需求或场景约束,否则更建议采用可重入锁以实现更为稳健高效的线程同步控制。
在Java标准库中并没有直接提供名为“不可重入锁”的内置锁,通常我们会通过对比ReentrantLock(可重入锁)来理解不可重入锁的概念。理论上,任何不具备可重入特性的锁都可以以为是不可重入锁。但在实际应用中,Java的synchronized关键字修饰的方法或代码块在早期版本中曾经存在过类似不可重入的行为,但在现在Java的全部版本中,synchronized关键字所实现的锁实际上是可重入的。
长处:
缺点:
基于锁的获取公平性

按照获取锁的公平性,也即哀求顺序,将锁分为公平锁盒非公平锁。
公平锁

公平锁是一种线程调度策略,在多线程情况下,当多个线程尝试获取锁时,锁的分配遵循“先哀求先服务”(First-Come, First-Served, FCFS)原则,即按照线程哀求锁的顺序来分配锁资源。这意味着等待时间最长的线程将优先得到锁。公平锁可以有用制止某个线程长期得不到锁而导致的饥饿现象,全部线程都有平等获取锁的机会。它确保了线程的调度更加有序,减少了不公平竞争导致的不确定性。
公平锁的实现,可以通过java.util.concurrent.locks.ReentrantLock的构造函数传入true参数,可以创建一个公平的ReentrantLock实例。
  1. ReentrantLock fairLock = new ReentrantLock(true); //创建一个公平锁
复制代码
长处:
缺点:
以下利用公平锁示例:
  1. public class FairLockExample {
  2.     private final ReentrantLock fairLock = new ReentrantLock(true); // 使用true参数创建公平锁
  3.     public void criticalSection() {
  4.         fairLock.lock(); // 获取公平锁
  5.         try {
  6.             // 在此区域内的代码是临界区,同一时间只有一个线程可以执行
  7.             System.out.println(Thread.currentThread().getName() + " entered the critical section at " + LocalDateTime.now());
  8.             // 模拟耗时操作
  9.             Thread.sleep(1000);
  10.         } catch (InterruptedException e) {
  11.             Thread.currentThread().interrupt();
  12.         } finally {
  13.             fairLock.unlock(); // 释放公平锁
  14.         }
  15.     }
  16.     public static void main(String[] args) {
  17.         final FairLockExample example = new FairLockExample();
  18.         Runnable task = () -> {
  19.             example.criticalSection();
  20.         };
  21.         // 创建并启动多个线程
  22.         for (int i = 0; i < 10; i++) {
  23.             Thread t = new Thread(task);
  24.             t.start();
  25.         }
  26.     }
  27. }
复制代码

在这个示例中,我们创建一个公平锁,我们创建了多个线程,每个线程都在实行criticalSection方法,该方法内部的代码块受到公平锁的保护,因此在任何时间只有一个线程能在临界区内实行。当多个线程尝试获取锁时,它们会按照哀求锁的顺序来获取锁,确保线程调度的公平性。
非公平锁

非公平锁是一种线程调度策略,在多线程情况下,当多个线程尝试获取锁时,锁的分配不遵循“先哀求先服务”(First-Come, First-Served, FCFS)原则,而是允许任何等待锁的线程在锁被开释时尝试获取,即使其他线程已经在等待队列中等待更长时间。非公平锁在某些场景下可以提高系统的并发性能,因为它允许刚开释锁的线程或者其他新到达的线程立刻获取锁,而不是强制列队等待。
实现方式也同公平锁,也是通过java.util.concurrent.locks.ReentrantLock的构造函数,但是我们要传入false参数,可以创建一个非公平的ReentrantLock实例。
  1. ReentrantLock fairLock = new ReentrantLock(false); //创建一个非公平锁
复制代码
长处:
缺点:
基于对共享资源的访问方式

我们常说或者常用的悲观锁以及乐观锁就是以对共享资源的访问方式来区分的。
悲观锁

悲观锁(Pessimistic Lock)是一种并发控制策略,它假设在并发情况下,多个线程对共享资源的访问极有可能发生辩说,因此在访问资源之前,先尝试获取并锁定资源,直到该线程完成对资源的访问并开释锁,其他线程才能继续访问。悲观锁的主要作用是在多线程情况中防止数据被并发修改,确保数据的一致性和完整性。当一个线程获取了悲观锁后,其他线程必须比及锁开释后才能访问相应资源,从而制止了数据竞态条件和脏读等题目。悲观锁适合写操纵较多且读操纵较少的并发场景。
而悲观锁的实现可以通过synchronized关键字实现的对象锁或类锁。或者通过java.util.concurrent.locks.Lock接口的实现类,如ReentrantLock。
悲观锁虽然在并发场景下数据的一致性和完整性。但是他却有一些缺点,例如:
以下我们利用显式锁ReentrantLock实现一个悲观锁的示例:
  1. import java.util.concurrent.locks.ReentrantLock;
  2. public class Account {
  3.     private final ReentrantLock lock = new ReentrantLock();
  4.     private double balance;
  5.     public void deposit(double amount) {
  6.         lock.lock();
  7.         try {
  8.             // 持有锁进行存款操作
  9.             balance += amount;
  10.             // 更新账户余额的其他逻辑...
  11.         } finally {
  12.             lock.unlock(); // 保证锁一定会被释放
  13.         }
  14.     }
  15.     public void withdraw(double amount) {
  16.         lock.lock();
  17.         try {
  18.             // 持有锁进行取款操作
  19.             if (balance >= amount) {
  20.                 balance -= amount;
  21.                 // 更新账户余额的其他逻辑...
  22.             }
  23.         } finally {
  24.             lock.unlock();
  25.         }
  26.     }
  27. }
复制代码
乐观锁

乐观锁并不是Java自己提供的某种内置锁机制,而是指一种并发控制策略,它基于乐观假设:即在并发访问情况下,以为数据竞争不太可能发生,以是在读取数据时并不会立即加锁。乐观锁适用于读多写少的场景或者并发较少的场景。
Java中的乐观锁通过CAS(Compare and Swap / Compare and Set)算法实现,而数据库层面我们常利用版本号或者时间戳等进行控制。
CAS(Compare and Swap / Compare and Set): Java提供了java.util.concurrent.atomic包中的原子类,如AtomicInteger、AtomicLong等,它们通过CAS操纵来实现乐观锁。CAS操纵是一个原子指令,它只会修改数据,当且仅当该数据的当前值等于预期值时才进行修改。例如,AtomicInteger中的compareAndSet方法就是在乐观锁思想下实现的一种无锁化更新操纵。
  1. import java.util.concurrent.atomic.AtomicInteger;
  2. AtomicInteger counter = new AtomicInteger(0);
  3. // 乐观锁更新示例
  4. public void incrementCounter() {
  5.     while (true) {
  6.         int expected = counter.get();
  7.         int updated = expected + 1;
  8.         if (counter.compareAndSet(expected, updated)) {
  9.             // 更新成功,退出循环
  10.             break;
  11.         }
  12.         // 更新失败,意味着有其他线程在此期间改变了值,继续尝试
  13.     }
  14. }
复制代码
长处:
缺点:
基于锁的升级以及优化

在Java中,JVM为了解决多线程情况下的同步题目,对锁机制进行了优化,将其分为偏向锁、轻量级锁和重量级锁三种状态。
偏向锁

偏向锁是一种Java假造机(JVM)在多线程情况下优化同步性能的锁机制,它适用于大多数时间只有一个线程访问同步代码块的场景。当一个线程访问同步代码块时,JVM会把锁偏向于这个线程,后续该线程在进入和退出同步代码块时,无需再做任何同步操纵,从而大大降低了获取锁和开释锁的开销。偏向锁是Java内存模型中锁的三种状态之一,位于轻量级锁和重量级锁之前。
长处
对于没有或很少发生锁竞争的场景,偏向锁可以显著减少锁的获取和开释所带来的性能损耗。
缺点
轻量级锁

轻量级锁是一种在Java假造机(JVM)中实现的同步机制,主要用于提高多线程情况下锁的性能。它不像传统的重量级锁那样,每次获取或开释锁都需要操纵系统级别的互斥操纵,而是尽量在用户态完成锁的获取与开释,制止了频繁的线程阻塞和叫醒带来的开销。轻量级锁的作用主要是减少线程上下文切换的开销,通过自旋(spin-wait)的方式让线程在一段时间内等待锁的开释,而不是立即挂起线程,如许在锁竞争不是很激烈的情况下,能够快速得到锁,提高程序的相应速度和并发性能。
在Java中,轻量级锁主要作为JVM锁状态的一种,它介于偏向锁和重量级锁之间。当JVM发现偏向锁不再适用(即锁的竞争不再局限于单个线程)时,会将锁升级为轻量级锁。
轻量级锁适用于同步代码块实行速度快、线程持有锁的时间较短且锁竞争不激烈的场景,如短期内只有一个或少数几个线程竞争同一线程资源的情况。
在Java中,轻量级锁的具体实现体现在java.util.concurrent.locks包中的Lock接口的一个具体实现:java.util.concurrent.locks.ReentrantLock,它支持可配置为公平或非公平模式的轻量级锁机制,当利用默认构造函数时,默认是非公平锁(类似于轻量级锁的非公平性子)。不过,JVM的内置synchronized关键字在JDK 1.6之后引入了锁升级机制,也包含了偏向锁和轻量级锁的优化。
长处
缺点
重量级锁

重量级锁是指在多线程编程中,为了保护共享资源而接纳的一种较为传统的互斥同步机制,通常涉及到操纵系统的互斥量(Mutex)或者监视器锁(Monitor)。在Java中,通过synchronized关键字实现的锁机制在默认情况下就是重量级锁。确保任何时刻只有一个线程能够访问被锁定的资源或代码块,防止数据竞争和不一致。保证了线程间的协同工作,确保在并发情况下实行的线程按照预定的顺序或条件进行操纵。
在Java中,重量级锁主要指的是由synchronized关键字实现的锁,它在JVM内部由Monitor实现,属于内建的锁机制。别的,java.util.concurrent.locks包下的ReentrantLock等类也可实现重量级锁,这些锁可以根据需要调整为公平锁或非公平锁。
长处
缺点
重量级锁适用于
在Java中,偏向锁、轻量级锁和重量级锁之间的转换是Java假造机(JVM)为了优化多线程同步性能而设计的一种动态调整机制。转换条件如下:
锁状态的转换是为了在不同的并发情况下,既能保证数据的正确性,又能尽可能地提高系统性能。JVM会根据实际情况自动调整锁的状态,无需我们手动干预。
分段锁

分段锁(Segmented Lock 或 Partitions Lock)是一种将数据或资源划分为多个段(segments),并对每个段分配单独锁的锁机制。如许做的目的是将锁的粒度细化,以便在高并发场景下提高系统的并发性能和可扩展性,特殊是针对大型数据结构如哈希表时非常有用。通过减少锁的粒度,可以使得在多线程情况下,不同线程可以同时访问不同段的数据,减小了锁争抢,提高了系统的并行处理能力。在大规模数据结构中,如果只有一个全局锁,可能会因为热点区域引发大量的锁竞争,分段锁则能有用地分散锁的压力。
Java中,分段锁在实现上可以基于哈希表的分段锁,例如Java中的ConcurrentHashMap,将整个哈希表分割为多个段(Segment),每个段有自己的锁,如许多个线程可以同时对不同段进行操纵。例外也可以基于数组或链表的分段锁,根据数据索引将数据分布到不同的段,每段对应一个独立的锁。
分段锁可以提高并发性能,减少锁竞争,增加系统的并行处理能力。其长处:
分段锁也有一些缺点:
分段锁适用于大数据结构的并发访问,如高并发情况下对哈希表的操纵。以及分布式系统中,某些分布式缓存或数据库系统也采用类似的分片锁策略来提高并发性能。
自旋锁

自旋锁(Spin Lock)是一种简单的锁机制,用于多线程情况中的同步控制,它的工作原理是当一个线程试图获取已经被另一个线程持有的锁时,该线程不会立即进入就寝状态(阻塞),而是不停地循环检查锁是否已经被开释,直到获取到锁为止。这种“循环等待”的行为被称为“自旋”。自旋锁主要用于保证同一时刻只有一个线程访问临界区资源,防止数据竞争。相比传统阻塞式锁,自旋锁在持有锁的线程很快开释锁的情况下,可以减少线程的上下文切换开销。
我们利用AtomicInteger实现一个简单的自旋锁:
  1. import java.util.concurrent.atomic.AtomicInteger;
  2. class SimpleSpinLock {
  3.     private AtomicInteger locked = new AtomicInteger(0);
  4.     public void lock() {
  5.         while (locked.getAndSet(1) == 1) {
  6.             // 自旋等待
  7.         }
  8.         // 已经获取锁,执行临界区代码
  9.     }
  10.     public void unlock() {
  11.         locked.set(0);
  12.     }
  13. }
复制代码
自旋锁长处
自旋锁缺点
死锁

说到各种锁,就会想到死锁题目,对于死锁有兴趣的可以参考这篇文章:
这里就不过多赘述。
总结

本文介绍了多种Java中的锁机制,包罗可重入锁(Reentrant Lock)、公平锁、非公平锁、悲观锁、乐观锁、偏向锁、轻量级锁、重量级锁、分段锁以及自旋锁。这些锁各有优缺点和适用场景,如可重入锁支持递归锁定,悲观锁确保数据一致性但可能引起性能开销,乐观锁在读多写少场景下表现优异,偏向锁和轻量级锁用于优化单线程重复访问,重量级锁提供严格的互斥性,分段锁通过减小锁粒度提高并发性能,而自旋锁则在短时间内获取锁的场景中能减少线程上下文切换。根据不同的并发需求和性能考量,开辟者可以选择符合的锁机制。
本文已收录于我的个人博客:码农Academy的博客,专注分享Java技术干货,包罗Java基础、Spring Boot、Spring Cloud、Mysql、Redis、Elasticsearch、中心件、架构设计、面试题、程序员攻略等

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4