目录
-
Lock接口的实现类
-
ReentrantLock的方法
-
ReentrantLockTest测试
-
用于测试的线程
-
t1测试
-
正确释放重入锁
-
获取当前的重入次数
-
-
t1t2测试
- 使用islocked()方法检测锁状态
-
t1t3测试
-
使用trylock方法尝试获取锁
-
使用isHeldByCurrentThread方法检测当前线程是否持有锁
-
不持有锁时调用unlock方法
-
-
t1t4测试
-
使用lockInterruptbly()尝试获取锁
-
中断因为lockInterruptbly()阻塞的线程
-
-
t1t2t3t4测试
-
使用hasQueuedThreads方法检测是否有线程在等待此锁
-
使用getQueueLength方法检测等待此锁的线程数量
-
使用hasQueuedThread方法检测指定线程是否在等待此锁
-
使用isFair检测此锁是否为公平锁
-
-
ReentrantLock锁
Lock接口的实现类
ReentrantLock即可重入锁
效果同synchronized关键字
ReentrantLock的方法
public String toString()
返回标识此锁的字符串,以及其锁状态。括号中的状态包括字符串 “Unlocked” 或字符串 “Locked by”,后跟拥有线程的名称。
public int getWaitQueueLength(Condition condition)
返回在与该锁关联的给定条件下等待的线程数的估计值。请注意,由于超时和中断可能随时发生,因此该估计仅用作实际服务员人数的上限。此方法旨在用于监视系统状态,而不是用于同步控制。
public boolean hasWaiters(Condition condition)
查询是否有任何线程正在等待与此锁关联的给定条件。请注意,由于超时和中断可能随时发生,因此真实的返回并不能保证将来的信号会唤醒任何线程。此方法主要设计用于监视系统状态。
public final boolean hasQueuedThread(Thread thread)
查询给定线程是否正在等待获取此锁。请注意,由于取消可能随时发生,因此真正的返回并不能保证该线程将永远获得此锁。此方法主要设计用于监视系统状态。
public final int getQueueLength()
返回等待获取此锁的线程数的估计值。该值只是一个估计值,因为在该方法遍历内部数据结构时,线程数可能会动态变化。此方法旨在用于监视系统状态,而不是用于同步控制。
public final boolean hasQueuedThreads()
查询是否有任何线程在等待获取此锁。请注意,由于取消可能随时发生,因此真正的返回并不能保证任何其他线程都将获得此锁。此方法主要设计用于监视系统状态。
public final boolean isFair()
如果此锁的公平设置为true,则返回true
public boolean isLocked()
查询此锁是否由任何线程持有。此方法旨在用于监视系统状态,而不是用于同步控制。
public int getHoldCount()
查询当前线程对此锁的保留数。
线程对每个锁定动作都有一个锁定,而解锁动作不匹配。
public boolean isHeldByCurrentThread()
查询此锁是否由当前线程持有。
类似于内置监视器锁的Thread.holdsLock(Object) 方法,该方法通常用于调试和测试。
public ReentrantLock()
创建ReentrantLock的实例。这相当于使用ReentrantLock(false)。
public ReentrantLock(boolean fair)
使用给定的公平策略创建ReentrantLock实例。(true表示公平锁策略)
ReentrantLockTest测试
用于测试的线程
Thread t1 = new Thread(() -> {for (int i = 0; i < 2; i++) {try {lock.lock();System.out.println("t1获取锁:lock.lock()");lock.lock();//每次循环重复获取锁2次System.out.println("t1获取锁:lock.lock()");} finally {System.out.println("t1释放锁:lock.unlock()");lock.unlock();//每次循环只释放一次锁}}System.out.println("t1当前对lock的获取次数:" + lock.getHoldCount());});Thread t2 = new Thread(() -> {try {System.out.println("t2线程 lock.lock()");lock.lock();System.out.println("t2获取到锁:lock");} finally {lock.unlock();}});Thread t3 = new Thread(() -> {try {System.out.println("t3使用trylock()尝试获取锁");if (lock.tryLock())System.out.println("t3线程获取了锁");elseSystem.out.println("t3获取锁失败");} finally {if (lock.isHeldByCurrentThread())lock.unlock();elseSystem.out.println("t3没有获取到锁 不需要执行unlock()");}});Thread t4 = new Thread(() -> {try {System.out.println("t4使用lockInterruptibly()尝试获取锁");lock.lockInterruptibly();System.out.println("t4获取到了锁");} catch (InterruptedException e) {System.out.println("t4在等待lock释放时被中断");e.printStackTrace();} finally {if (lock.isHeldByCurrentThread()) {lock.unlock();} else {System.out.println("t4没有获取到锁 不需要执行unlock()");}}});
t1测试
System.out.println("\nt1线程启动");t1.start();Thread.sleep(100);
正确释放重入锁
t1线程此时并没有释放锁
ReentrantLock的机制为:
如果一个线程获取了此锁
则可以在后续多次重复获取
但也需要相同次数的释放
才能正确的释放锁
获取当前的重入次数
t1线程获取锁共4次
释放锁2次
剩余2次获取没有释放
在线程循环外通过lock.getHoldCount()得到了线程t1对lock的重入次数
t1t2测试
System.out.println("\nt1线程启动");t1.start();Thread.sleep(100);System.out.println(lock.isLocked());System.out.println("\nt2线程启动");t2.start();Thread.sleep(100);
使用islocked()方法检测锁状态
如果锁已经被某个线程获取
islocked方法返回true
否则返回false
因为线程t1没有正确释放重入锁 t2没有获取到锁
t1t3测试
System.out.println("\nt1线程启动");t1.start();Thread.sleep(100);
System.out.println("\nt3线程启动");t3.start();Thread.sleep(100);
使用trylock方法尝试获取锁
trylock尝试获取锁
如果获取成功 返回true
如果获取失败 返回false 且不会阻塞等待锁释放
使用isHeldByCurrentThread方法检测当前线程是否持有锁
如果当前线程持有此锁返回true
如果当前线程不持有锁返回false
不持有锁时调用unlock方法
如果线程在没有获取到此锁的情况下使用了此锁unlock方法
会抛出illegalMonitorStateException
t3中
在释放锁之前使用isHeldByCurrentThread检测
避免在不持有锁时释放锁
t1t4测试
System.out.println("\nt1线程启动");t1.start();Thread.sleep(100);System.out.println("\nt4线程启动");t4.start();Thread.sleep(100);t4.interruput();
使用lockInterruptbly()尝试获取锁
当获取成功 效果同lock()
当获取失败 阻塞等待锁释放 但此线程在阻塞期间可以响应中断
中断因为lockInterruptbly()阻塞的线程
当线程因为lockInterruptbly()阻塞时
如果收到中断请求
会抛出interruptedException
效果同sleep wait期间收到中断请求
可以捕获异常进行中断处理
t1t2t3t4测试
System.out.println("\nt1线程启动");t1.start();Thread.sleep(100);System.out.println("\nt2线程启动");t2.start();Thread.sleep(100);System.out.println("\nt3线程启动");t3.start();Thread.sleep(100);System.out.println("\nt4线程启动");t4.start();Thread.sleep(100);System.out.println("\nlock锁的检测方法:");System.out.println("是否有线程在等待lock锁:"+lock.hasQueuedThreads());System.out.println("有多少线程在等待lock锁:"+lock.getQueueLength());System.out.println("t2线程是否在等待lock锁:"+lock.hasQueuedThread(t2));System.out.println("lock是否为公平锁:"+lock.isFair());
使用hasQueuedThreads方法检测是否有线程在等待此锁
如果返回true说明有线程在等待此锁
否则返回false
使用getQueueLength方法检测等待此锁的线程数量
返回的整数代表等待此锁的线程数量
此处t2 t4线程在等待锁
t3线程使用trylock()没有获取到锁 已经执行else路径的代码退出 没有阻塞等待lock释放
使用hasQueuedThread方法检测指定线程是否在等待此锁
如果返回true 代表此线程正在等待此锁释放
如果返回false代表此线程没在等待此锁
使用isFair检测此锁是否为公平锁
如果返回true 代表此锁是公平锁
如果返回false代表此锁不是公平锁
公平锁即 请求获取此锁的线程按请求顺序依次获得锁
非公平锁即 所有请求获取此锁的线程随机竞争