关于可重入锁,公平锁和非公平锁

可重入锁

首先明白可重入锁的概念:就是在一个线程中可以重复加锁

在一个线程中可以重复加锁,使用的ReentrantLock()​就是一种可重入锁

例子:

   public static void main(String[] args) throws InterruptedException {
    ReentrantLock lock = new ReentrantLock();
    lock.lock();
    lock.lock();
        System.out.println("当前锁个数"+lock.getHoldCount()+"锁"+lock.isLocked());
        lock.unlock();
        System.out.println("当前锁个数"+lock.getHoldCount()+"锁是否被释放"+lock.isLocked());
        lock.unlock();
        System.out.println("当前锁个数"+lock.getHoldCount()+"锁是否被释放"+lock.isLocked());
    }

​getHoldCount()​用来查看当前线程的加锁次数。isLocked()​用来查看当前线程是否有锁

实际上当一个线程持有锁的时候,其他线程想要获取锁会进入一个等待队列的

可以使用getQueueLength()​来获取当前等待获取锁的线程数

例子:

 public static void main(String[] args) throws InterruptedException {


    ReentrantLock lock = new ReentrantLock();
    Thread t1 = new Thread(lock::lock), t2 = new Thread(lock::lock),t3 = new Thread(lock::lock);
    t1.start();
    t2.start();
    t3.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("当前等待锁释放的线程数:"+lock.getQueueLength());
        System.out.println("线程1是否在等待队列中:"+lock.hasQueuedThread(t1));
        System.out.println("线程2是否在等待队列中:"+lock.hasQueuedThread(t2));
        System.out.println("线程3是否在等待队列中:"+lock.hasQueuedThread(t3));
        System.out.println("当前线程是否在等待队列中:"+lock.hasQueuedThread(Thread.currentThread()));

 }
//        当前等待锁释放的线程数:2
//        线程1是否在等待队列中:false
//        线程2是否在等待队列中:true
//        线程3是否在等待队列中:true
//        当前线程是否在等待队列中:false

可以看到2,3线程都在等待队列中

公平锁和非公平锁

前面我们知道,当出现多个线程争抢一把锁的时候会进入等待队列,那么争抢的顺序一定是按,获取锁的代码顺序来的吗?

来看看ReentrantLock​的构造方法

public ReentrantLock() {
    sync = new NonfairSync();   //看名字貌似是非公平的
}

其实锁可以分为公平锁和非公平锁,上面的实现类默认采用的是非公平锁

  • 公平锁:多个线程按照申请锁的顺序依次进入队列,永远是第一个进入的先获取到缩进
  • 非公平锁:当一个线程要获取锁的时候,直接先去尝试获取锁,如果得到了,那就不进入等待队列,没有得到的话就进入等待队列
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

这是另外一种构造方法,用来确定是哪一种锁

例子

    public static void main(String[] args) throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        Runnable action = () -> {
            System.out.println(Thread.currentThread().getName() + " is running");
            lock.lock();
            System.out.println(Thread.currentThread().getName() + " is locked");
            lock.unlock();
        };
        for (int i = 0; i < 10; i++) {
            new Thread(action,"T"+i).start();
        }

    }
//        T0 is running
//        T3 is running
//        T2 is running
//        T1 is running
//        T5 is running
//        T0 is locked
//        T4 is running
//        T4 is locked
//        T6 is running
//        T7 is running
//        T6 is locked
//        T8 is running
//        T3 is locked
//        T9 is running
//        T2 is locked
//        T1 is locked
//        T5 is locked
//        T7 is locked
//        T8 is locked
//        T9 is locked

 

可以看到T4在T0释放锁之后获取了锁,这显然和顺序是不同的,如果是顺序的话,那么应该是T3先获取锁才对

再来看公平锁,直接将参数改为true​

        ReentrantLock lock = new ReentrantLock(true);
//		  T0 is running
//        T4 is running
//        T3 is running
//        T6 is running
//        T1 is running
//        T7 is running
//        T2 is running
//        T8 is running
//        T0 is locked
//        T5 is running
//        T9 is running
//        T4 is locked
//        T3 is locked
//        T6 is locked
//        T1 is locked
//        T7 is locked
//        T2 is locked
//        T8 is locked
//        T5 is locked
//        T9 is locked

可以看到这边就是按顺序的获取锁

t0->t4->t3->t6...

以上就是关于文章的全部内容,希望对你有所帮助!!!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值