至于公平的ReentrantReadWriteLock,如果线程t1持有读锁并忘记解锁,而线程t2试图获取写入锁,那么所有试图获取读或写锁的后续线程都将永远阻塞。
但是,jstack -l只能检测哪个线程持有写入锁,但不能检测哪个线程持有读锁。
有没有一种方法可以检测哪个线程持有读锁?
例如,
public static void main(String[] args) throws InterruptedException {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
Thread t1 = new Thread(() -> {
lock.readLock().lock();
try {
// Sleep long time.
Thread.sleep(1000_000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
});
t1.start();
Thread t2 = new Thread(() -> {
lock.writeLock().lock();
try {
System.out.println("t2");
} finally {
lock.writeLock().unlock();
}
});
t2.start();
Thread t3 = new Thread(() -> {
lock.readLock().lock();
try {
System.out.println("t3");
} finally {
lock.readLock().unlock();
}
});
t3.start();
t1.join();
t2.join();
t3.join();
}jstack -l的结果如下。在Locked ownable synchronizers of Thread-0中什么都没有。
"Thread-2" #13 prio=5 os_prio=31 tid=0x00007f7d0c04e000 nid=0x5903 waiting on condition [0x000070000d399000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076ac17400> (a java.util.concurrent.locks.ReentrantReadWriteLock$FairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireShared(AbstractQueuedSynchronizer.java:967)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireShared(AbstractQueuedSynchronizer.java:1283)
at java.util.concurrent.locks.ReentrantReadWriteLock$ReadLock.lock(ReentrantReadWriteLock.java:727)
at WaWaMain.lambda$main$2(WaWaMain.java:30)
at WaWaMain$$Lambda$3/1149319664.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"Thread-1" #12 prio=5 os_prio=31 tid=0x00007f7d0c04d000 nid=0x5703 waiting on condition [0x000070000d296000]
java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x000000076ac17400> (a java.util.concurrent.locks.ReentrantReadWriteLock$FairSync)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(AbstractQueuedSynchronizer.java:836)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireQueued(AbstractQueuedSynchronizer.java:870)
at java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:1199)
at java.util.concurrent.locks.ReentrantReadWriteLock$WriteLock.lock(ReentrantReadWriteLock.java:943)
at WaWaMain.lambda$main$1(WaWaMain.java:20)
at WaWaMain$$Lambda$2/558638686.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None
"Thread-0" #11 prio=5 os_prio=31 tid=0x00007f7d0c809000 nid=0x5503 waiting on condition [0x000070000d193000]
java.lang.Thread.State: TIMED_WAITING (sleeping)
at java.lang.Thread.sleep(Native Method)
at WaWaMain.lambda$main$0(WaWaMain.java:12)
at WaWaMain$$Lambda$1/1747585824.run(Unknown Source)
at java.lang.Thread.run(Thread.java:745)
Locked ownable synchronizers:
- None发布于 2022-07-16 17:07:19
这个程序中的问题主要是因为t2线程,它试图获得一个写锁,原因是它想要一个互斥锁。它不会获得这个锁,因为线程t1未能解锁读取锁。但是,线程t3将不受影响,因为它正在寻找处于共享模式的读锁,因此即使t1没有解锁读锁,t3仍然可以工作。因此,这个程序的唯一方法是,如果线程t2是第一个获得锁(即写锁)的线程。
关于如何获得具有锁的线程的名称的实际问题,我没有这个问题的答案。但是问题是,如果它是一个没有被解锁的写锁,那么在某个时候,只有一个线程会有一个写锁,因为它是相互排斥的,所以我相信jStack可以很容易地检测和显示这一点。但是,当涉及到试图获得读锁的线程时,可能会有几个线程导致问题。希望这能回答这个问题。
https://stackoverflow.com/questions/72963244
复制相似问题