【Java学习笔记(八十三)】之 ReentrantLock类,Condition类,ReentrantReadWriteLock类

本文章由公号【开发小鸽】发布!欢迎关注!!!


老规矩–妹妹镇楼:

一. Lock的使用

(一) ReentrantLock类

       之前我们使用了synchronized关键字实现线程之间的同步互斥,在JDK1.5中添加了ReentrantLock类也能够达到同样的效果,并且扩展了新的功能。

1. lock() 与 unlock()

       创建一个新的ReentrantLock锁对象,调用该锁对象的lock()方法获得锁,线程调用了该方法,就持有了对象监视器,其他线程只有等待锁被释放时再次争抢。同样的,调用该所对象的unlock()方法释放锁。

private Lock lock = new ReentrantLock();
lock.lock();
lock.unlock();

(二) Condition类

       我们可以通过Condition对象实现等待/通知模式,这是在JDK5中出现的技术,有较好的灵活性,可以实现多路通知,即在一个Lock对象内创建多个Condition(对象监视器)实例,线程对象可以注册在指定的Condition中,从而可以有选择性地进行线程通知。而synchronized相当于整个Lock对象中只有一个单一的Condition对象,所有线程都注册在一个对象上,通知是随机的。

private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
contion.await();
condition,signal();

       首先在一个线程中调用Lock对象的lock()方法获取锁对象,然后调用Condition对象的await()方法,使当前执行任务的线程进入等待状态,最后调用Condition对象的signal()方法,通知该Condition对象处理等待中的线程。还有signalAll()方法是唤醒所有等待的线程。

       将不同的线程注册到不同的Condition对象中,通过调用不同的Condition对象的notifyAll()方法或者notify()方法就可以控制唤醒的线程对象。

(三) 生产者/消费者模式

       与之前使用wait()/notify()一样,这里使用的是Condition对象的await()/signal(), signalAll()方法。

(四) 公平锁与非公平锁

       锁对象Lock分为公平锁和非公平锁。公平锁表示线程获取锁的顺序是按照线程加锁的顺序来分配的,即先来先得的FIFO顺序,但是只能保证大多数是按照顺序的,总会有少数不按顺序分配的。而非公平锁就是随机获取锁的机制。

       在创建ReentrantLock锁对象的时候,传入一个Boolean值表示是否是公平锁:

Lock lock = new ReentrantLock(true);

(五) Lock锁对象的方法

1. getHoldCount()

       该方法查询当前线程保持此锁对象的个数,也就是该锁对象调用lock()方法的次数。

lock.getHoldCount();

2. getQueueLength()

       返回正在等待获取此锁对象的线程估计数,如共有5个线程,当1个线程先执行了await()方法后,那么还有4个线程在等待着该锁对象的释放。

lock.getQueueLength();

3. getWaitQueueLength(Condition condition)

       返回等待与此锁对象相关的给定条件Condition的线程估计数,如有5个线程,每个线程都绑定在同一个Condition对象上,并且调用了该Condition对象的await()方法,则调用getWaitQueueLength(Condition condition)方法返回的是5。关键点是那个Conditino对象绑定的线程数量。

lock.getWaitQueueLength(newCondition);

4. hasQueuedThread()

       查询是否有线程正在等待获取此锁对象。

lock.hasQueuedThread();

5. hasQueuedThread(Thread thread)

       查询指定的线程是否正在等待获取此锁对象。

lock.hasQueuedThread(thread);

6. hasWaiters(Condition condition)

       查询是否有线程正在等待与此锁对象有关的Condition条件

lock.hasWaiters(condition);

7. isFair()

       判断当前的锁对象是不是公平锁,默认的情况下,ReentrantLock类使用的是非公平锁。

lock.isFair();

8. isHeldByCurrentThread()

       查询当前线程是否保持着这个锁对象,这个方法通常用在释放锁对象的时候,先判断再释放。

lock.isHeldByCurrentThread();

9. isLocked()

       查询此锁对象是否由任意的线程保持着,即锁对象是否正在被使用。

lock.isLocked();

10. lockInterruptibly()

       如果当前线程未被终端,则可以获取该锁对象,如果已经被中断了,则出现异常。

lock.lockInterruptibly();

11. Boolean tryLock()

       当某线程调用该方法时,只有在调用时锁对象未被另一个线程持有的情况下,才能够获取该锁对象。

lock.tryLock();

12. Boolean tryLock(long timeout, TimeUnit unit)

       如果锁对象在给定的等待时间内没有被另一个线程获取,且当前线程未被中断,则获取该锁对象。

lock.tryLock(3, TimeUnit.SECONDS);

(六) Condition对象的方法

1. awaitUninterruptibly()

       与await()方法的区别是,当前线程调用该方法后,即使线程被中断了,也不会出现异常,而await()方法被中断时,立即会出现异常。

condition.awaitUninterruptibly();

2. awaitUntil(Time)

       进入等待状态Time时间,之后会自动唤醒。也可以由其他的线程来提前唤醒。

condition.awaitUntil(Time);

(七) ReentrantReadWriteLock类

1. 概述

       虽然ReentrantLock类能够实现完全互斥的功能,但是同一时刻只有一个线程在执行ReentrantLock.lock()后面的任务,十分低效。因此,引出了一个新的读写锁ReentrantReadWriteLock类。

2. 读锁与写锁

       读写锁有两个锁,一个是与读操作相关的锁,称为共享锁;一个是与写操作相关的锁,称为排它锁。很显然,多个读锁之间不是互斥的,读锁与写锁是互斥的,多个写锁是互斥的。

3. 读锁
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.readLock().lock();
lock.readLock().unlock();

4. 写锁
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
lock.writeLock().lock();
lock.writeLock().unlock();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值