Java中的各种锁

1.公平锁和非公平锁
    公平锁:多个线程按照申请锁的顺序来获取锁;(类似排队打饭,先来后到)
非公平锁:多个线程并非按照申请锁的顺序,有可能后申请的线程先得到锁。(在高并发场景下,有可能会造成优先级反转或饥饿现象)
实现原理:多线程场景下,如果去检查锁维护的等待队列,如果队列为空或当前线程是队列中的队首元素则获取锁,否则就会加入等待队列,按照FIFO的规则等到排队到自己再获取锁。非公平锁上来就尝试去抢占锁,没有成功再排队。
ReentrantLock 默认是非公平锁,比公平锁性能好,吞吐量更大。
Synchronized 也是非公平锁.

2.可重入锁和递归锁
可重入锁就是递归锁,就相当于一个别名.
可重入锁:同一线程外层方法获取锁后,内层递归调用的方法仍自动获取这把锁。
即,线程可以进入任何一个它已经拥有的锁所同步着的代码块
ReentrantLock/Synchronized 就是一个经典的可重入锁
作用:防止死锁

锁的基本原理是,基于将多线程并行任务通过某一种机制实现线程的串行执行,从而达到线程安全性的目的。

3.自旋锁
尝试获取锁的线程不会阻塞,而是采用死循环的方式去获取锁
这样做的好处是减少了线程上下文切换的消耗,缺点是死循环很耗CPU。
下面这段是 CAS 自旋锁的源码

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;
}

生活中自旋的例子:一个人饿了到食堂等着开饭;求人办事在别人办公室一直等着别人有空;

4.读写锁/互斥锁
共享锁:即读锁;指该锁可以同时被多个线程持有。
独占锁:即写锁;一次只能被一个线程所持有。ReentrantLock/Synchronized就是独占锁。
互斥锁:
读 - 读 能共存;
读 - 写 不能共存;
写 - 写 不能共存;

读写锁维护了一对锁,一个读锁、一个写锁; 一般情况下,读写锁的性能都会比排它锁好,因为大多数场景读是多于写的。
在读多于写的情况下,读写锁能够提供比排它锁更好的并发性和吞吐量.

5.分段锁

6.乐观锁/悲观锁
基于乐观锁以及自旋锁来优化了 synchronized 的加锁开销;
同时在重量级锁阶段,通过线程的阻塞以及唤醒来达到线程竞争和同步的目的。

7.偏向锁/轻量级锁/重量级锁

8.独享锁/共享锁

Java提供了种类丰富的,每种因其特性的不同,在适当的场景下能够展现出非常高的效率[^1]。以下是几种常见的介绍: ### 悲观 悲观秉持悲观思想,认为写操作多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上,这样别人想读写这个数据就会阻塞直到拿到Java中的`Synchronized`就是悲观,AQS框架下的则是先尝试CAS乐观去获取,获取不到,才会转换为悲观,如`ReentrantLock` [^3]。 ### 可重入 Java中`ReentrantLock`和`synchronized`都是可重入,可重入的一个优点是可在一定程度避免死。例如以下代码展示了`synchronized`和`ReentrantLock`的可重入性: ```java import java.util.concurrent.locks.ReentrantLock; public class ReentrantLockExample { static Object lock = new Object(); public static void main(String[] args) { // synchronized 可重入示例 synchronized (lock) { System.out.println("第一层"); synchronized (lock) { System.out.println("第二层"); } } // ReentrantLock 可重入示例 ReentrantLock reentrantLock = new ReentrantLock(); try { reentrantLock.lock(); reentrantLock.lock(); reentrantLock.unlock(); } finally { reentrantLock.unlock(); } } } ``` 在上述代码中,`synchronized`块和`ReentrantLock`都可以多次获取,体现了可重入性 [^4]。 ### `synchronized`与`Lock`对比 `synchronized`足够清晰简单,只需要基础的同步功能时,适合使用`synchronized`。使用`synchronized`时,JVM确保即使出现异常,也能被自动释放;而使用`Lock`时,应该确保在`finally`块中释放,且Java虚拟机很难得知哪些对象是由特定线程持有的 [^2]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值