如何判断是否当前线程持有锁
背景
有时候我们必须知道是否当前线程持有锁,怎么知道
- 如果用synchronized,用
Thread.holdsLock(lockObj)
获取 - 如果使用 Lock(juc下的),则用
lock.isHeldByCurrentThread()
(不能用 Thread.holdsLock(lockObj))
注意 Lock 接口本身是没有 isHeldByCurrentThread 接口的,必须使用ReentrantLock、ReentrantWriteLock这些实现类。
注意
ReentrantReadLock 没有 isHeldByCurrentThread()。因为ReentrantReadLock作为读锁根本就不需要获得锁从而没有这个方法
ReentrantReadWriteLock 也没有这个方法
代码验证
package com.wyf.test.is_cur_thread_hold_lock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* 判断当前线程是否持有锁
* 结论:
* 只有使用 synchronized 的时候,这个 Thread.holdsLock(lockObj) 才能否正确判断,在 Lock 里总是返回false(而且你也不知道holdsLock的入参传什么,holdsLock的
* 参数其实就是synchronized的锁对象,所以Lock里调用 Thread.holdsLock(lockObj) 根本就讲不通
*/
public class IsCurThreadHoldLock {
public static void main(String[] args) {
testSynchronized();// 通过 Thread.holdsLock(lockObj) 检查当前线程是否持有锁对象
//testLock();// Lock 不能通过 Thread.holdsLock(lockObj)
//testLockByIsHeldByCurrentThread();// 可以通过 ReentrantLock#isHeldByCurrentThread() 来判断
//testLockByIsHeldByCurrentThread2();// 可以通过 ReentrantWriteLock#isHeldByCurrentThread() 来判断
}
private static void testSynchronized() {
Object lockObj = new Object();
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ",before:" + Thread.holdsLock(lockObj));
synchronized (lockObj) {
System.out.println(Thread.currentThread().getName() + ",in:" + Thread.holdsLock(lockObj));
sleep(5);
}
System.out.println(Thread.currentThread().getName() + ",after:" + Thread.holdsLock(lockObj));
}, "t0").start();
sleep(1);
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + ",before:" + Thread.holdsLock(lockObj));
sleep(1);
}, "t1").start();
}
private static void testLock() {
Lock lock = new ReentrantLock();
new Thread(() -> {
// 传 lock 到 Thread.holdsLock 方法里是很荒谬的
System.out.println(Thread.currentThread().getName() + ",before:" + Thread.holdsLock(lock));
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + ",in:" + Thread.holdsLock(lock));
sleep(5);
} finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName() + ",after:" + Thread.holdsLock(lock));
}, "t0").start();
sleep(1);
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + ",before:" + Thread.holdsLock(lock));
sleep(1);
} finally {
}
}, "t1").start();
}
private static void testLockByIsHeldByCurrentThread() {
// 必须使用具体的实现类, Lock 接口里没有 isHeldByCurrentThread 方法
ReentrantLock lock = new ReentrantLock();
new Thread(() -> {
// 传 lock 到 Thread.holdsLock 方法里是很荒谬的
System.out.println(Thread.currentThread().getName() + ",before:" + lock.isHeldByCurrentThread());
try {
lock.lock();
System.out.println(Thread.currentThread().getName() + ",in:" + lock.isHeldByCurrentThread());
sleep(5);
} finally {
lock.unlock();
}
System.out.println(Thread.currentThread().getName() + ",after:" + lock.isHeldByCurrentThread());
}, "t0").start();
sleep(1);
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + ",before:" + lock.isHeldByCurrentThread());
sleep(1);
} finally {
}
}, "t1").start();
}
private static void testLockByIsHeldByCurrentThread2() {
// 必须使用具体的实现类, Lock 接口里没有 isHeldByCurrentThread 方法
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
ReentrantReadWriteLock.ReadLock readLock = lock.readLock();// 没有 isHeldByCurrentThread接口,读锁不需要获得锁,所以就没有
ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
new Thread(() -> {
// 传 lock 到 Thread.holdsLock 方法里是很荒谬的
System.out.println(Thread.currentThread().getName() + ",before:" + writeLock.isHeldByCurrentThread());
try {
writeLock.lock();
System.out.println(Thread.currentThread().getName() + ",in:" + writeLock.isHeldByCurrentThread());
sleep(5);
} finally {
writeLock.unlock();
}
System.out.println(Thread.currentThread().getName() + ",after:" + writeLock.isHeldByCurrentThread());
}, "t0").start();
sleep(1);
new Thread(() -> {
try {
System.out.println(Thread.currentThread().getName() + ",before:" + writeLock.isHeldByCurrentThread());
sleep(1);
} finally {
}
}, "t1").start();
}
private static void sleep(int secs) {
try {
TimeUnit.SECONDS.sleep(secs);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}