主要并发工具类-ReentrantLock的使用

2020-02-10  本文已影响0人  飞奔吧牛牛

ReentrantLock 在使用上比synchronized稍微复杂点,需要显示的获取锁和释放锁。
synchronized属于非公平锁,当多个线程去竞争同一个锁时,具体哪个线程会获取到锁不确定。ReentrantLock 除了支持非公平锁外,还支持公平锁,即获取锁的先后顺序已经确定,后来的会排到最后。
基本使用形式:

 ReentrantLock lock = new ReentrantLock();
        lock.lock();
        try {
            System.out.println("do something");
        } finally {
            lock.unlock();
        }

常用的四个方法:
lock.lock() 获取锁
lock.unLock() 释放锁
lock.tryLock() 立即去获取锁,获取到返回true,获取不到返回false
lock.tryLock(TimeOut,TimeUnit) 在一段时间内尝试获取锁,在这段时间内获取到了锁,返回true,超时后返回false。

以上四个方法的使用:
1.初始化lock对象

ReentrantLock lock = new ReentrantLock();

2.在线程t1中使用锁,获取锁后休眠3秒。休眠完后,释放锁

 Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                System.out.println(Thread.currentThread().getName() + " lock success");
                try {
                    TimeUnit.SECONDS.sleep(3);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(Thread.currentThread().getName()+" unlock");
                    lock.unlock();
                }
            }
        });

3.在线程t2中尝试获取锁,成功失败都打印相应信息。

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    if (lock.tryLock(1, TimeUnit.SECONDS)) {
                        System.out.println(Thread.currentThread().getName() + " tryLock success");
                        try {
                            TimeUnit.SECONDS.sleep(1);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } finally {
                            lock.unlock();
                        }
                    } else {
                        System.out.println(Thread.currentThread().getName() + "tryLock failure");
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                    System.out.println("等待获取锁时被打断");
                }
            }
        });

4.确保t1先执行,再执行t2。

    t1.start();
        TimeUnit.SECONDS.sleep(1);
        t2.start();

4.1 tryLock等待时间超时的情况。
t1先执行,拿到锁后立刻休眠三秒。t1执行一秒后,t2执行。这时t2 tryLock(1, TimeUnit.SECONDS),由于在这一秒内,锁一直被t1持有,
超时后拿不到锁,故打印:Thread-1tryLock failure。之后t1休眠完毕,释放锁。

Thread-0 lock success
Thread-1tryLock failure
Thread-0 unlock

4.2 tryLock成功获取到锁的情况。
修改等待获取锁的时间,即if (lock.tryLock(3, TimeUnit.SECONDS))。
由于t2 tryLock等待的时间足够长,当t1执行完毕后释放了锁,这时,还在t2 tryLock等待时间之内,所以会立即获取锁。

Thread-0 lock success
Thread-0 unlock
Thread-1 tryLock success

可见ReentrantLock功能更多,当sychronized不能满足需求时,可以使用ReentrantLock。

上一篇下一篇

猜你喜欢

热点阅读