基本锁的理解(待补充)

简介: 可重入锁允许同一线程多次获取同一锁而不致死锁;不可重入锁则不允许递归锁定,连续调用会致死锁。死锁发生在多进程争夺资源导致僵局。读锁允许多线程并发读取,写锁则排他。自旋锁通过循环等待获取锁;共享锁用于只读操作;排它锁用于数据修改;闭锁延迟线程直至状态终止;信号量控制对资源的访问,未获信号量的线程会进入睡眠状态。

==可重入锁==:当一个线程获取一个对象上的锁的时候,会自动获取该对象的其他锁,而其他线程不可获取该对象的任何锁(一般都是可重复锁)
可重入锁的代码示例:

public class Lock{
   
    boolean isLocked = false;
    Thread  lockedBy = null;
    int lockedCount = 0;
    public synchronized void lock()
            throws InterruptedException{
   
        Thread thread = Thread.currentThread();
        while(isLocked && lockedBy != thread){
   
            wait();
        }
        isLocked = true;
        lockedCount++;
        lockedBy = thread;
    }
    public synchronized void unlock(){
   
        if(Thread.currentThread() == this.lockedBy){
   
            lockedCount--;
            if(lockedCount == 0){
   
                isLocked = false;
                notify();
            }
        }
    }
}

==不可重入锁==:当一个线程获取一个对象上外层方法的锁的时候,如果接下来的方法又需要获取另一个锁,则需要先等待锁释放才能获取下一个
不可重入锁的代码示例:

public class Lock{
   
    private boolean isLocked = false;
    public synchronized void lock() throws InterruptedException{
   
        while(isLocked){
       
            wait();
        }
        isLocked = true;
    }
    public synchronized void unlock(){
   
        isLocked = false;
        notify();
    }
}

如果再同一个方法里,连续调用两次 lock() 方法,会发生死锁。

==死锁==: 多个进程在运行过程之中因争夺资源而造成的一种僵局

==读锁==: 可以共享,多个线程可以同时拥有读锁
==写锁==: 只能只有一个线程拥有,而且获取写锁的时候其他线程都已经释放了读锁,该线程获取写锁之后,其他线程不能再获取读锁。简单的说就是写锁是排他锁,读锁是共享锁。Java中实现读写锁的类是:ReentrantReadWriteLock;
保证一定能读到最新数据,修改期间,写锁是一个排它锁(互斥锁、独享锁),读锁是一个共享锁
写锁没释放读锁必须等待
读 + 读 :相当于无锁,并发读,只会在Redis中记录好,所有当前的读锁。他们都会同时加锁成功
写 + 读 :必须等待写锁释放
写 + 写 :阻塞方式
读 + 写 :有读锁。写也需要等待
只要有读或者写的存都必须等待

==自旋锁==:是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。

==共享锁==:用于不更改数据的、只读、查询等操作,如 SELECT 语句,读文件等。获取共享锁的事务只能读数据,不能修改数据。

==排它锁=:用于数据的修改,比如 INSERT,UPDATE,或 DELETE,同一资源在同一时间只能有一个用户获得排它锁。

==闭锁==:闭锁是一种同步工具类,可以延迟线程的进度直到其到达终止状态;

==信号量==:和自旋锁一样,信号量也是保护临界资源的一种有用方法。信号量只有当得到信号量时,进程或者线程才能够进入临界区,执行临界代码。

信号量与自旋锁的最大不同点在于,当一个进程试图去获取一个已经锁定的信号量时,该进程不会像自旋锁一样在自旋忙等待,而是会将自身加入一个等待队列中去睡眠,直到其他进程释放信号量后,处于等待队列中的进程才会被唤醒。当进程唤醒之后,就立刻重新从睡眠的地方开始执行,又一次试图获得信号量,当获得信号量后,程序继续执行。

所以,从信号量的原理上来说,没有获得信号量的函数可能睡眠。这就要求只有能够睡眠的进程才能够使用信号量,不能睡眠的进程不能使用信号量。例如中断处理程序中,由于中断需要立刻完成,所以不能睡眠,也就是说在中断处理程序中不能使用信号量。

相关文章
|
7月前
|
存储 人工智能 关系型数据库
10个行锁、死锁案例⭐️24张加锁分析图🚀彻底搞懂Innodb行锁加锁规则!
10个行锁、死锁案例⭐️24张加锁分析图🚀彻底搞懂Innodb行锁加锁规则!
|
4月前
|
Java 开发者
解锁Java并发编程的秘密武器!揭秘AQS,让你的代码从此告别‘锁’事烦恼,多线程同步不再是梦!
【8月更文挑战第25天】AbstractQueuedSynchronizer(AQS)是Java并发包中的核心组件,作为多种同步工具类(如ReentrantLock和CountDownLatch等)的基础。AQS通过维护一个表示同步状态的`state`变量和一个FIFO线程等待队列,提供了一种高效灵活的同步机制。它支持独占式和共享式两种资源访问模式。内部使用CLH锁队列管理等待线程,当线程尝试获取已持有的锁时,会被放入队列并阻塞,直至锁被释放。AQS的巧妙设计极大地丰富了Java并发编程的能力。
49 0
|
安全 算法 Java
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
|
7月前
|
安全 Java
java多线程之Lock锁原理以及案例实现电影院卖票
java多线程之Lock锁原理以及案例实现电影院卖票
|
设计模式 安全 Java
JUC第十二讲:JUC锁 - 看不懂锁核心类 AQS 原理来打我
JUC第十二讲:JUC锁 - 看不懂锁核心类 AQS 原理来打我
|
机器学习/深度学习 算法 安全
二十二、死锁
二十二、死锁
二十二、死锁
|
数据采集 缓存 算法
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
141 0
库调多了,都忘了最基础的概念 《锁与线程 2 终结篇》
|
存储 安全 Java
小白也能看懂的锁升级过程和锁状态
小白也能看懂的锁升级过程和锁状态
265 0
小白也能看懂的锁升级过程和锁状态
|
设计模式 算法 Java
可重复锁ReentrantLock原理分析(2)
可重复锁ReentrantLock原理分析(2)
116 0
可重复锁ReentrantLock原理分析(2)