Java同步的字符串IllegalMonitorStateException
作者:互联网
我正在尝试让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();
}
}
除了高亮显示string.notifyAll()外,StackTrace中什么也没有.
解决方法:
>您的代码包含数据争用,因为它访问同步块外部的可变字符串变量.具体来说,这发生在synced(string)行上.当取消引用字符串以到达其监视器将被锁定的对象时,线程尚未对该对象持有锁定.因此,您无法保证它将锁定哪个对象.
>更改字符串变量的事实意味着它现在指向其他对象.当下一个线程获得对该新对象的锁定时,它将不会从任何之前发生的关系中受益,因为它是有史以来第一个获得对其锁定的线程.也不保证相互排斥,因为可能有任意多个线程,每个线程锁定一个不同的String实例而没有争用.
>结合上述两种现象,我们还可以看到,不能保证在synced(string)行上到达的对象将与从synced块内到达的对象相同.一旦碰巧这确实是一个不同的对象,就会发生IllegalMonitorStateException.
总之,情况与根本不存在的同步块非常相似.
如果您坚持使用专用的最终变量来引用用于锁定的对象的最佳做法,则可以避免上述所有问题.简而言之,并修复示例中的编译错误,这是您必须编写的:
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();
}
标签:java,multithreading,blackberry 来源: https://codeday.me/bug/20191013/1906512.html