美文网首页程序员
ReentrantLock 可重入锁

ReentrantLock 可重入锁

作者: 尉昌达 | 来源:发表于2020-07-07 07:26 被阅读0次
  1. boolean tryLock(long time, TimeUnit unit)

Lock lock = new ReentrantLock();
lock.tryLock(5, TimeUnit.SECONDS); //在5秒之内尝试获得锁,超时后未获得锁返回false

public class T03_ReentrantLock3 {
    Lock lock = new ReentrantLock();

    void m1() {
        try {
            lock.lock();
            for (int i = 0; i < 3; i++) {
                TimeUnit.SECONDS.sleep(1);

                System.out.println(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    /**
     * 使用tryLock进行尝试锁定,不管锁定与否,方法都将继续执行
     * 可以根据tryLock的返回值来判定是否锁定
     * 也可以指定tryLock的时间,由于tryLock(time)抛出异常,所以要注意unclock的处理,必须放到finally中
     */
    void m2() {
        /*
        boolean locked = lock.tryLock();
        System.out.println("m2 ..." + locked);
        if(locked) lock.unlock();
        */
        
        boolean locked = false;
        
        try {
            locked = lock.tryLock(5, TimeUnit.SECONDS);
            System.out.println("m2 ..." + locked);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if(locked) lock.unlock();
        }
        
    }

    public static void main(String[] args) {
        T03_ReentrantLock3 rl = new T03_ReentrantLock3();
        new Thread(rl::m1).start();
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(rl::m2).start();
    }
}

上面m1()结束后,m2()会获得锁,locked=true;

  1. lockInterruptibly()

public static void main(String[] args) {
        Lock lock = new ReentrantLock();
        
        
        Thread t1 = new Thread(()->{
            try {
                lock.lock();
                System.out.println("t1 start");
                TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
                System.out.println("t1 end");
            } catch (InterruptedException e) {
                System.out.println("interrupted!");
            } finally {
                lock.unlock();
            }
        });
        t1.start();
        
        Thread t2 = new Thread(()->{
            try {
                //lock.lock();
                lock.lockInterruptibly(); //可以对interrupt()方法做出响应
                System.out.println("t2 start");
                TimeUnit.SECONDS.sleep(5);
                System.out.println("t2 end");
            } catch (InterruptedException e) {
                System.out.println("interrupted!");
            } finally {
                lock.unlock();
            }
        });
        t2.start();
        
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t2.interrupt(); //打断线程2的等待
        
    }

运行输出:
t1 start
interrupted!

上面t1会一直运行,t2获取不到锁,t2.interrupt()之后,t2被打断,抛出异常

  1. ReentrantLock lock=new ReentrantLock(true);

  • reentrantLock默认是非公平锁,可以设置为公平锁,公平锁的话,内部会有一个队列,若果锁被他人占有,其他要获的锁的线程会依次入队列,每次获得锁的时候要去判断队列是否为空,为空直接获得锁。而非公平锁直接去抢占锁。
  1. 与synchronized的区别

  • synchronized系统自动加锁,自动解锁,ReentrantLock需要手动控制。
  • ReentrantLock可以有不同的condition,不同的等待队列,synchronized没有
  • synchronized有锁的四种状态的升级,ReentrantLock用的CAS的实现。

相关文章

网友评论

    本文标题:ReentrantLock 可重入锁

    本文链接:https://www.haomeiwen.com/subject/dmdnqktx.html