我正在尝试在另一个方法中使用synchronized语句运行一个方法。
MyClass的
public class MyClass {
private Object lockObject = new Object();
public void testFirst() {
synchronized (lockObject) {
System.out.println("Entered testFirst() sync");
testSecond();
System.out.println("Leaving testFirst() sync");
}
}
private void testSecond() {
synchronized (lockObject) {
System.out.println("Entered testSecond() sync");
}
}
}
主要
package com.replanet;
public class Main {
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.testFirst();
}
}
输出
Entered testFirst() sync
Entered testSecond() sync
Leaving testFirst() sync
我期待另一个输出。
Entered testFirst() sync
Leaving testFirst() sync
Entered testSecond() sync
为什么testSecond()
不会等到testFirst()
完成工作?
答案 0 :(得分:4)
您看到这种看似奇怪的行为,因为每个锁与请求它的线程相关联,一旦您获得锁定,您就会保留它直到您解锁。
在你的代码中,你获得了两次相同的锁,所以第二次尝试会立即成功,因为你已经拥有它。
请参阅here以获取参考:
当一个线程正在为一个对象执行一个synchronized方法时,所有其他线程会调用同一个对象块的同步方法(暂停执行),直到第一个线程完成该对象为止。
答案 1 :(得分:3)
由于要输入第一个synchronized
部分,您必须锁定对象lockObject
,当您到达第二个synchronized
部分时,您仍然可以继续使用它。运行testFirst
时,synchronized
中的testSecond
块不会发生任何变化。
答案 2 :(得分:2)
要记住的一些事项:
synchronized
块是可重入的:当您通过synchronized
语句保持锁定时,您可以使用同一个监视器输入另一个synchronized
块 - 在您的情况下,没有什么可以阻止您调用来自testSecond
testFirst
testSecond
的锁testSecond
中使用的锁testFirst
的执行不会跳过拨打testSecond
并继续前进,它会阻止,直到锁定再次可用答案 3 :(得分:1)
Beause testSecond()与 testFirst()
相关联控制流程完全如下: -
System.out.println("Entered testFirst() sync");
System.out.println("Entered testSecond() sync");
System.out.println("Leaving testFirst() sync");
答案 4 :(得分:1)
同步是围绕一个称为内在锁或监视器锁的内部实体构建的 每个对象都有一个与之关联的内在锁。按照惯例,需要对对象字段进行独占和一致访问的线程必须在访问对象之前获取对象的内部锁,然后在完成它们时释放内部锁。据说一个线程在获得锁定和释放锁定之间拥有内在锁定。只要一个线程拥有一个内部锁,没有其他线程可以获得相同的锁。另一个线程在尝试获取锁时会阻塞。
所以你的线程是lockObject的所有者,因此它可以使用lockObject
进入块内的所有代码答案 5 :(得分:0)
我编辑了我发布的代码。同步语句有意义,不是吗?
<强> MyClass的强>
public class MyClass {
private Object lockObject = new Object();
public void testFirst() throws InterruptedException {
// Here is something that should not be synchronized
synchronized (lockObject) {
System.out.println("testFirst() is about to fall asleep. "
+ Thread.currentThread().getName());
Thread.sleep(2000);
System.out.println("testFirst() woke up. " + Thread.currentThread().getName());
}
}
}
<强> MyThread的强>
public class MyThread extends Thread {
private MyClass myClass;
public MyThread(MyClass myClass) {
this.myClass = myClass;
}
@Override
public void run() {
try {
myClass.testFirst();
} catch (InterruptedException e) {
interrupt();
}
super.run();
}
}
<强>用法强>
package com.replanet;
public class Main {
public static void main(String[] args) {
MyClass myClass = new MyClass();
MyThread mThread = new MyThread(myClass);
MyThread anotherThread = new MyThread(myClass);
mThread.start();
anotherThread.start();
}
}
<强>输出强>
testFirst() is about to fall asleep. Thread-0
testFirst() woke up. Thread-0
testFirst() is about to fall asleep. Thread-1
testFirst() woke up. Thread-1