公平锁与非公平锁

公平锁与非公平锁

# 公平锁与非公平锁
公平锁:
多个线程按照申请锁的顺序来获取锁,先来后到,在并发环境中,每个线程在获取锁时会先查看此锁维护的等待队列,如果为空,或者当前线程等待队列的第一个,就占有锁,否则就会加入到等待队列,以后会按照FIFO的规则从队列中取。
非公平锁:
多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程获取锁。在高并发的情况下,哟可能会造成优先级反转或者饥饿现象。

ReentrantLock类 :默认是非公平锁,在构造函数中加参数true,会创建公平锁。

非公平锁的优点:非公平锁的吞吐量大

ReentrantLock的构造器,默认时new 一个非公平的锁。

 非公平锁有哪几种ReentrantLock,synchronized


 可重入锁,也叫递归锁

 可重入锁:指的是同一个线程外层函数获得锁之后,内层递归函数仍然能获取该锁的代码,在同一个线程在外层方法获取锁的时候,进入内层方法会自动获取锁  

 种类:ReentrantLock 和 synchronized 都是可重入锁 

 作用:避免死锁 

注意点:用了锁,一定要记得开锁和关锁,lock和unlock方法都是一对一对的出现,避免出现错误,如果少了其中的一个,就会报错。

ReentrantLock  版本:

public class MyLock_1 {
    
    public static void main(String[] args) {
        Mylock(); 
        new Thread(()->{
            Mylock();
        }).start();
    }

   static ReentrantLock reentrantLock = new ReentrantLock();
    public static void Mylock(){
        reentrantLock.lock();
        try {
            System.out.println("第一把锁:"+Thread.currentThread().getId());
            Lock lock = new ReentrantLock();
            lock.lock();
            try {
                System.out.println("第二把锁:"+Thread.currentThread().getId());
            }finally {
                lock.unlock();
            }
        }catch (Exception ex){
            ex.printStackTrace();
        }finally {
            reentrantLock.unlock();
        }
    }
}
结果:
synchronized 版本:其实一层里面再套一层,多层,但是获取到的对象都是第一把锁,锁住的对象。
public class Xttblog {
    public static void main(String[] args) {
        Xttblog child = new Xttblog();
        child.doSomething();
    }
 
    public synchronized void doSomething() {
        System.out.println("child.doSomething()" + Thread.currentThread().getName());
        doAnotherThing(); // 调用自己类中其他的synchronized方法
    }
 
    private synchronized void doAnotherThing() {
        super.doSomething(); // 调用父类的synchronized方法
        System.out.println("child.doAnotherThing()" + Thread.currentThread().getName());
    }
}
 
class SuperXttblog {
    public synchronized void doSomething() {
        System.out.println("father.doSomething()" + Thread.currentThread().getName());
    }
}

结果:

 可重入锁的原理: 详情到时看 ReentrantLock 源码 

重入锁实现可重入性原理或机制是:每一个锁关联一个线程持有者和计数器,当计数器为 0 时表示该锁没有被任何线程持有,那么任何线程都可能获得该锁而调用相应的方法;

当某一线程请求成功后,JVM会记下锁的持有线程,并且将计数器置为 1;此时其它线程请求该锁,则必须等待;而该持有锁的线程如果再次请求这个锁,就可以再次拿到这个锁,

同时计数器会递增;当线程退出同步代码块时,计数器会递减,如果计数器为 0,则释放该锁。

原文地址:https://www.cnblogs.com/cb1186512739/p/12743252.html