并发系列(十一)----- ReentrantLock的使用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MyPersonalSong/article/details/84545790

一 简介

ReentrantLock在中文的意思是重入锁与synchronized同步语意一样(具体的区别下面会总结),重入的意思是一个线程可以多次加锁,但是释放锁的时候要释放加锁的次数。ReentrantLock实现就是利用AQS独占模式,内部维护了一个AQS的子类Sync,Sync有两个子类FairSync和NofairSync这两个分别是ReentrantLock的两种锁,公平锁和非公平锁(公平锁与非公平锁介绍)。因为ReentrantLock利用了AQS的独占模式,那么ReentrantLock就可以使用等待队列的相关功能。

二 ReentrantLock的简单使用

如果只是简单使用ReentrantLock,不使用同步队列的话是比较简单。使用方式如下

    /**
     * ReentrantLock默认是非公平锁 公平锁的创建 private static final ReentrantLock lock = new ReentrantLock(true);
     */
    private static final ReentrantLock lock = new ReentrantLock();
    public void doSomeThing(){
        lock.lock();
        try {
            //执行业务逻辑,在这里操作可保证线程安全
        }finally {
            lock.unlock();
        }
    }

使用方式是比较简单,但是ReentrantLock提供加锁的方式却有不同的方式,具体说明如下

锁定释放只有一个方法unlock()。

三 ReentrantLock等待队列的使用

在ReentrantLock中的Condition提供了Object中的wait(),和notify(),notifyAll()的功能,其中在Condition中的await开头的方法与Object中的wait具有相同的功能,Condition中的signal()和signalAll()分别相当与Object中的notify()和notifyAll(),其中一个lock总可已有多个Condition

下面看代码

 private static ReentrantLock lock = new ReentrantLock();

    private static Condition condition = lock.newCondition();

    public static void main(String[] args) {


        final Thread hh = new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    System.out.println(Thread.currentThread() + "等待条件完成");
                    condition.await();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    System.out.println(Thread.currentThread() + "终于等到条件完成了");
                    lock.unlock();
                }
            }
        });
        hh.start();

        final Thread qq = new Thread(new Runnable() {
            @Override
            public void run() {
                lock.lock();
                try {
                    System.out.println(Thread.currentThread() + "条件完成了");
                    this.notifyAll();
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    lock.unlock();
                }
            }
        });
        qq.start();
    }

下面是等待相关的方法说明

唤醒的话是两个方法signal()和singalAll()两个方法,作用的话看方法名就知道了。一个是只唤醒一个,一个是唤醒所有。

四 与synchronized的区别

ReentrantLock和synchronized具有相同的功能,在性能上不会有太大的差别,如果既可以用ReentrantLock也可以用synchronized的话,官方的建议是使用synchronized。因为synchronized在使用的时候比较方便的不用考虑释放锁,而ReentrantLock如果没有释放的话会是其它线程一直处于waiting状态中。但是ReentrantLock也有它特有的功能

1.      ReenTrantLock可以指定是公平锁还是非公平锁。而synchronized只能是非公平锁。所谓的公平锁就是先等待的线程先获得锁。

2.      ReenTrantLock提供了一个Condition(条件)类,用来实现分组唤醒需要唤醒的线程们,而不是像synchronized要么随机唤醒一个线程要么唤醒全部线程。

3.      ReenTrantLock提供了一种能够中断等待锁的线程的机制lock()方法

在同步的时候有上面3需要ReentrantLock的功能可以使用ReenTrantLock,在其他的情况下听官方的。

猜你喜欢

转载自blog.csdn.net/MyPersonalSong/article/details/84545790