阅读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次被释放,那么线程应该继续锁定锁?
发布于 2018-07-31 15:42:21
您的问题:“代码显示只需要一个锁操作,还是我遗漏了什么?”已经得到了“皮特·柯克姆”的回答。
主要问题的答案是“需要多少解锁操作才能解锁Java中多次锁定的对象?”就是你引用的那个。
下面的代码显示了Thread t1如何“多次锁定特定监视器”,以及“每次解锁都会逆转一次锁定操作的效果”。
Thread t1三次进入synchronize块。每次输入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为我运行。
发布于 2018-07-31 14:43:19
此代码没有对对象的状态做任何操作:
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获取一个锁,打印程序的唯一输出,然后释放锁。
主线程获取一个锁,通知一个等待的线程,然后释放锁。
因此,有几个顺序,线程可以获得锁,所有这些都导致相同的输出。
https://stackoverflow.com/questions/51615261
复制相似问题