在Java中,一个被多次锁定的对象需要多少次解锁操作才能解锁



阅读java语言规范-内存模型,我可以通过这条语句进行查看。

线程t可以多次锁定特定监视器;每次解锁反转一次锁定操作的效果。

然后我用下面的代码尝试了一下,但它似乎不起作用。要么我不理解该语句,要么我的代码没有按我希望的方式执行。。。

public class MultipleLocks {

private static final Object LOCK = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronized (LOCK) {
//some code ...
}
}

synchronized (LOCK) {
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
synchronized (LOCK) {
System.out.println("I can acquire a lock !");
}
});
t2.start();
synchronized (LOCK) {
LOCK.notify();
}
}

}

11-锁只解锁一次

代码显示只需要一次锁定操作,或者我遗漏了什么?

编辑:

如果我的代码是错误的,我如何模拟获取锁n次并释放它n次,如果释放了n-1次,那么线程应该继续锁定锁?

这段代码对对象的状态没有任何作用:

for (int i = 0; i < 10; i++) {
synchronized (LOCK) { // lock gained on LOCK object
//some code ...
} // lock released on LOCK object
}

锁定在同步块开始时获得,并在结束时释放。这样做十次会使对象处于与循环开始时相同的状态。

Thread1然后获取锁,然后等待,这导致它释放锁,直到另一个线程通知对象。

线程释放此监视器的所有权,并等待另一个监视器线程通知在该对象的监视器上等待唤醒的线程Object.wait((javadocs

Thread2获取锁,打印程序的唯一输出,然后释放锁。

主线程获取一个锁,通知一个等待的线程,然后释放锁。

因此,线程可以按照几个顺序获取锁,所有这些顺序都会产生相同的输出。

您的问题">代码显示只需要一次锁定操作,或者我缺少了什么?"已由@Pete Kirkham回答。

主要问题">在Java中多次锁定的对象需要多少次解锁操作才能解锁?"的答案就是您引用的答案。

以下代码显示Thread t1如何">多次锁定特定监视器"以及"每次解锁都会逆转一次锁定操作的效果。"。

CCD_ 2进入CCD_ 3块三次。每次进入synchronize块时,都会获得一个(附加(锁。每次留下synchronize块时,都会释放一个锁。因此,首先在t1离开所有synchronize块之后,Thread t2可以进入synchronize块。

public class Locking {
private static Object o = new Object();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(Locking::lockSeveralTimes);
Thread t2 = new Thread(Locking::lockOnce);
t1.start();
Thread.sleep(100); // give t1 some time to start
t2.start();
}
protected static void lockOnce() {
synchronized (o) {
System.out.println("DONE");
}
}
protected static void lockSeveralTimes() {
try {
System.out.println("Has Lock: " + Thread.holdsLock(o));
synchronized (o) {
System.out.println("Aquired Lock: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
waitOneSecond();
synchronized (o) {
System.out.println("Aquired Lock: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
waitOneSecond();
synchronized (o) {
System.out.println("Aquired Lock: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
waitOneSecond();
System.out.println("Going to release lock. Still holds: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
}
waitOneSecond();
System.out.println("Going to release lock. Still holds: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
}
waitOneSecond();
System.out.println("Going to release lock. Still holds: " + Thread.holdsLock(o) + " / Times: " + getLockedMonitorsCount());
}
System.out.println("Still holds: " + Thread.holdsLock(o));
} catch (Exception e) {
e.printStackTrace();
}
}
protected static void waitOneSecond() throws InterruptedException {
Thread.sleep(1000);
}
protected static int getLockedMonitorsCount() {
return ManagementFactory.getThreadMXBean().getThreadInfo(new long[] { Thread.currentThread().getId() }, true, false)[0].getLockedMonitors().length;
}
}

输出为:

Has Lock: false
Aquired Lock: true / Times: 1
Aquired Lock: true / Times: 2
Aquired Lock: true / Times: 3
Going to release lock. Still holds: true / Times: 3
Going to release lock. Still holds: true / Times: 2
Going to release lock. Still holds: true / Times: 1
Still holds: false
DONE

使用JDK 8为我运行。

最新更新