基本锁的理解(待补充)

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

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

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,同一资源在同一时间只能有一个用户获得排它锁。

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

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

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

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

相关文章
|
5月前
|
存储 人工智能 关系型数据库
10个行锁、死锁案例⭐️24张加锁分析图🚀彻底搞懂Innodb行锁加锁规则!
10个行锁、死锁案例⭐️24张加锁分析图🚀彻底搞懂Innodb行锁加锁规则!
|
2月前
|
Java
什么是 CAS(自旋锁)? 它的优缺点? 如何使用CAS实现一把锁?
该博客文章解释了什么是CAS(自旋锁),包括CAS的基本概念、实现原理、优缺点,以及如何使用CAS实现锁的逻辑,并提供了使用CAS实现锁的Java完整代码示例和测试结果。
什么是 CAS(自旋锁)? 它的优缺点? 如何使用CAS实现一把锁?
|
4月前
|
调度
mutex和原⼦锁混⽤导致mutex失效的情况和原因
mutex和原⼦锁混⽤导致mutex失效的情况和原因
|
4月前
|
Python
Python多线程中递归锁如何解决死锁问题的详细阐述
Python多线程中递归锁如何解决死锁问题的详细阐述
|
安全 算法 Java
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
可重入锁,不可重入锁,死锁的多种情况,以及产生的原因,如何解决,synchronized采用的锁策略(渣女圣经)自适应的底层,锁清除,锁粗化,CAS的部分应用
|
缓存 Linux 容器
深入了解锁细节
深入了解锁细节
68 0
|
存储 安全 Java
大白话讲解synchronized锁升级套路
synchronized锁是啥?锁其实就是一个对象,随便哪一个都可以,Java中所有的对象都是锁,换句话说,Java中所有对象都可以成为锁。 这次我们主要聊的是synchronized锁升级的套路
116 0
|
关系型数据库 中间件 MySQL
上手全局锁,死锁
上手全局锁,死锁
上手全局锁,死锁
|
存储 安全 Java
看完你就明白的锁系列之锁的状态
前面两篇文章我介绍了一下 看完你就应该能明白的悲观锁和乐观锁 看完你就明白的锁系列之自旋锁 看完你就会知道,线程如果锁住了某个资源,致使其他线程无法访问的这种锁被称为悲观锁,相反,线程不锁住资源的锁被称为乐观锁,而自旋锁是基于 CAS 机制实现的,CAS又是乐观锁的一种实现,那么对于锁来说,多个线程同步访问某个资源的流程细节是否一样呢?换句话说,在多线程同步访问某个资源时,锁的状态会如何变化呢?本篇文章来探讨一下。
94 0
看完你就明白的锁系列之锁的状态
可重复锁ReentrantLock原理分析(2)
可重复锁ReentrantLock原理分析(2)
113 0
可重复锁ReentrantLock原理分析(2)