Java可重入锁ReentrantLock

在JDK1.5之前,我们设计程序进行线程之间通信时必须使用同步锁,获得同步锁必须使用同步关键字synchronized(lock)的形式。JDK1.5提供了线程同步相关的包java.util.concurrent,引入了可重入锁ReentrantLock,使用起来很方便并且提高了代码运行效率。可重入锁ReentrantLock从概念上理解是,此锁多线程可以分别分时拥有的意思,举个简单例程说明
在这里插入图片描述
我们发现线程A拥有锁Lock后,线程A停止执行时,线程B可以申请到重入锁Lock,当线程B停止执行时,线程C也可以申请到重入锁Lock,直到T4时刻,线程A,B,C分别释放重入锁Lock。

传统的同步锁是不允许其他线程重入的,是串行的,比如线程A从T1到T4拥有锁,其他线程在此期间是不可以申请到锁的。
在这里插入图片描述
重入锁ReentrantLock
在这里插入图片描述
线程间通信
重入锁ReentrantLock使用Condition进行线程间通信,传统锁使用wait,notify进行线程间通信。

Condition类的awiat方法=Object类的wait方法
Condition类的signal方
=Object类的notify方法
Condition类的signalAll方法===Object类的notifyAll方法
在这里插入图片描述
例程中调用condition.await(),线程将一直等待下去,不会结束程序,condition还可以等待一定时间。
在这里插入图片描述
上面例程中线程等待5秒钟后结束执行。

唤起线程执行使用condition.signal();
在这里插入图片描述
使用Condition进行线程间通信,各线程必须共享同一个Condition对象。这个有点类似传统的同步锁。

ReentrantLock锁类型

Lock lock=new ReentrantLock(true);//公平锁 Lock lock=new ReentrantLock(false);//非公平锁

ReentrantLock锁其他方法
getHoldCount() 查询当前线程保持此锁的次数,也就是执行此线程执行lock方法的次数
getQueueLength()返回正等待获取此锁的线程估计数,比如启动10个线程,1个线程获得锁,此时返回的是9
getWaitQueueLength(Condition condition)返回等待与此锁相关的给定条件的线程估计数。比如10个线程,用同一个condition对象,并且此时这10个线程都执行了condition对象的await方法,那么此时执行此方法返回10
hasWaiters(Condition condition)查询是否有线程等待与此锁有关的给定条件(condition),对于指定contidion对象,有多少线程执行了condition.await方法
hasQueuedThread(Thread thread)查询给定线程是否等待获取此锁
hasQueuedThreads()是否有线程等待此锁
isFair()该锁是否公平锁
isHeldByCurrentThread() 当前线程是否保持锁锁定,线程的执行lock方法的前后分别是false和true
isLock()此锁是否有任意线程占用
lockInterruptibly()如果当前线程未被中断,获取锁
tryLock()尝试获得锁,仅在调用时锁未被线程占用,获得锁
tryLock(long timeout TimeUnit unit)如果锁在给定等待时间内没有被另一个线程保持,则获取该锁

演示例程
在这里插入图片描述
运行结果
在这里插入图片描述
可以发现,重入锁等待队列中的线程从0增加到9,每一个线程休眠5秒钟,所有的10个线程都分别一次拥有了重入锁,其他线程等待时其他线程就可以拥有重入锁,所以所有线程打印的信息几乎时同一时间。
如果将condition.await(5,TimeUnit.SECONDS)替换成Thread.sleep(5000),执行结果变成如下
在这里插入图片描述
可以发现各线程打印信息的时间相差5秒钟,应该没有使用ReentrantLock的功能。

猜你喜欢

转载自blog.csdn.net/qixiang_chen/article/details/84204647