我试图让 Thread2 等待 String 并让 Thread1 通知 String 更新,我确实同步了 String 对象,如下面的代码所示,但我仍然得到IllegalMonitorStateException
这是我的代码
public class Class1{
String string = "";
public Class1(){
Thread t1 = new Thread(){
public void run(){
synchronized(string){
string = "Something"; string.notifyAll(); //This is the line that throws an IllegalMonitorStateException
}
}
};
Thread t2 = new Thread(){
public void run(){
synchronized(string){
try{
string.wait();
}catch(Exception e){
e.printStackTrace();
}
}
}
};
t2.start();
t1.start();
}
}
StackTrace 中除了突出显示之外没有任何内容string.notifyAll()
您的代码包含数据争用,因为它访问可变的string
a 之外的变量synchronized
堵塞。具体来说,这发生在线路上synchronized(string)
。取消引用时string
要到达监视器将被锁定的对象,线程尚未持有该对象的锁。因此,您无法保证它将获得哪个对象的锁。
事实是你mutate the string
变量意味着它现在指向某个其他对象。当下一个线程获取该新对象的锁时,它将不会从任何对象中受益发生在之前关系,因为它是第一个获取其锁的线程。互斥也无法保证,因为可能有任意多个线程,每个线程锁定不同的线程String
无争用的实例。
结合上面描述的两种现象我们也可以看出,并不能保证对象在线上到达synchronized(string)
将与从 到达的 相同within同步块。一旦碰巧这确实是一个不同的对象,你的IllegalMonitorStateException
ensues.
总结一下,情况与synchronized
块根本不存在。
如果您坚持使用专用的最佳实践,则可以避免上述所有问题final
变量来引用用于锁定的对象。简而言之,并修复示例中的编译错误,这就是您必须编写的内容:
static String string = "";
static final Object lock = new Object();
public static void main(String[] args) {
Thread t1 = new Thread() {
public void run() {
synchronized (lock) {
... update the string variable ...
lock.notifyAll();
}
}
};
Thread t2 = new Thread() {
public void run() {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
};
t2.start();
t1.start();
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)