对象上的Java同步。为什么';这不是僵局吗?
下面的构造可以正常工作并执行我想要的操作,但我想了解它为什么不会死锁 下面的示例确保用户在继续操作之前已在弹出的对象上的Java同步。为什么';这不是僵局吗?,java,multithreading,deadlock,synchronized,Java,Multithreading,Deadlock,Synchronized,下面的构造可以正常工作并执行我想要的操作,但我想了解它为什么不会死锁 下面的示例确保用户在继续操作之前已在弹出的JOptionPane框中单击是或否 package waitexample; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; public class WaitExample { public static void main(String[] args) throws Interru
JOptionPane
框中单击是或否
package waitexample;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
public class WaitExample {
public static void main(String[] args) throws InterruptedException {
System.out.println("starting");
Object myWaiter = new Object();
SwingUtilities.invokeLater(() -> {
System.out.println("invoked");
JOptionPane.showConfirmDialog(null, "Message", "Title", JOptionPane.YES_NO_OPTION);
synchronized (myWaiter) {
System.out.println("calling notify");
myWaiter.notify();
System.out.println("notified");
}
});
synchronized (myWaiter) {
System.out.println("waiting");
myWaiter.wait();
System.out.println("done waiting");
}
System.out.println("ending main()");
}
}
但是,考虑到以下输出,看起来我正在使用不同的线程同时输入synchronized(mywater)
块:
starting
waiting
invoked
calling notify
notified
done waiting
ending main()
为什么不会出现死锁?如果等待的线程在持有锁时处于休眠状态,则会出现死锁。但事实并非如此,尤其是第二段: 使当前线程等待,直到另一个线程为此对象调用notify()方法或notifyAll()方法。换句话说,此方法的行为完全类似于它只执行调用等待(0) 当前线程必须拥有此对象的监视器。线程释放此监视器的所有权并等待,直到另一个线程通过调用notify方法或notifyAll方法通知等待此对象监视器的线程唤醒。然后线程等待,直到它可以重新获得监视器的所有权并恢复执行 与单参数版本一样,中断和虚假唤醒是可能的,并且此方法应始终在循环中使用:
synchronized(obj){
而()
obj.wait();
…//执行适合条件的操作
}
此方法只能由作为此对象监视器所有者的线程调用。有关线程成为监视器所有者的方式的描述,请参见notify方法
当主线程进入wait方法时,它会释放在进入synchronized块时获取的锁,因此该锁可供EDT线程获取。在EDT上执行的Runnable找到可用的锁并获取它,对它调用notify,打印它的消息并退出synchronized块,释放锁。此时,主线程在退出wait方法之前获取锁,然后在存在块时释放锁
请注意,因为等待退出不是通知发生的证据,所以等待可以在没有任何通知发生的情况下退出(这是API文档中提到的虚假唤醒)。另外,虽然在这种情况下,通知代码正在等待UI控件的输入,因此主线程将首先等待,但一般来说,您不希望依赖于在通知之前发生的等待:如果通知确实首先发生,那么等待可能会无限期地继续下去。您可以通过在循环中调用wait来解决这两个问题(如上面文档中所建议的),在循环中检查通知代码设置的某些条件。引用文档 线程释放此监视器的所有权并等待另一个监视器 线程通知等待此对象监视器唤醒的线程 通过调用notify方法或notifyAll方法。 然后线程等待,直到它可以重新获得监视器的所有权 并恢复执行 这就解释了到
starting
waiting
invoked <- could have appeared before or after waiting
由于此时EDT线程放弃同步块并释放锁,因此下面几行代码如下:
done waiting
ending main()
对锁的等待将释放该锁,并在唤醒时重新获取该锁。感谢您提供的详细信息。但愿我能接受这两个答案。:-)
calling notify
notified
done waiting
ending main()