ReentrantLock的使用

  • Post author:
  • Post category:其他


(1)synchronized是独占锁,加锁和解锁的过程自动进行,易于操作,但不够灵活。ReentrantLock也是独占锁,加锁和解锁的过程需要手动进行,不易操作,但非常灵活。

(2)synchronized可重入,因为加锁和解锁自动进行,不必担心最后是否释放锁;ReentrantLock也可重入,但加锁和解锁需要手动进行,且次数需一样,否则其他线程无法获得锁。

(3)synchronized不可响应中断,一个线程获取不到锁就一直等着;ReentrantLock可以相应中断。

ReentrantLock公平锁,等待时间最长的线程先运行

首先做一个简易的售票功能

如下使用了reentrantlock公平锁,结果为

public class T1 {
    static int num = 23;
    static ReentrantLock lock = new ReentrantLock(true);

    public static void main(String[] args) {
        new Thread(T1::tt, "文化路").start();
        new Thread(T1::tt, "瑞达路").start();
        new Thread(T1::tt, "红旗路").start();
    }

    static void tt() {
        String na = Thread.currentThread().getName();

        while (num > 1) {
            lock.lock();
            num--;
            System.out.printf("%s:%d%n", na, num);
            if (num < 1) {
                break;
            }
            lock.unlock();
        }
    }
}

reentrantlock可以打断线程

例如一个线程睡眠时间太长,导致其他线程阻塞,则可以打断前一个进程。

public class T4 {
    static ReentrantLock lock = new ReentrantLock();

    public static void main(String[] args) {
        Thread a = new Thread(T4::add, "T1");
        a.start();
        a.interrupt();
        new Thread(() -> {
            try {
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {

                lock.lockInterruptibly();
                TimeUnit.SECONDS.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程二");
            lock.unlock();
        }).start();
    }

    static void add() {
        try {
            lock.lock();
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("11");
        lock.unlock();
    }
}
lockInterruptibly()获取锁,除非当前线程被中断。如果锁没有被其他线程持有,则获取锁并立即返回,将锁持有计数设置为1。如果当前线程已经持有这个锁,那么持有计数加1,该方法立即返回。如果锁被另一个线程持有,那么当前线程会因为线程调度的目的而被禁用,并处于休眠状态,直到发生以下两种情况之一:锁被当前线程获取;或其他线程中断当前线程。如果当前线程获得了锁,那么锁保持计数被设置为1如果当前线程:在进入此方法时设置其中断状态;或在获取锁时被中断然后,InterruptedException被抛出,当前线程的interruptec状态被清除。在此实现中,由于此方法是显式的中断点,因此优先于响应中断,而不是正常或可重入获取锁。



版权声明:本文为weixin_57176230原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。