我的代码给了我一个问题。
我的代码会在IllegalMonitorStateException
中抛出setStr
,这是Hoge类。
我将Hoge.class
更改为this
中的setStr
。我的代码正确完成了!
但为什么它正常结束?
public class Sample {
static Hoge gh = new Hoge();
static Hoge gh2 = new Hoge();
public static void main(String[] args) {
new Thread() {
private Hoge h2 = gh;
public void run() {
System.out.println("start initialize");
h2.setStr("BazzBazz");
System.out.println("end initialize");
System.out.println("start thread 1");
System.out.println(h2.getStr("thread-1"));
System.out.println("end thread 1");
}
}.start();
new Thread() {
private Hoge h2 = gh2;
public void run() {
System.out.println("start thread 2");
System.out.println(h2.getStr("thread-2"));
System.out.println("end thread 2");
}
}.start();
}
}
class Hoge {
private String fuga = "fugafuga";
public void setStr(String str) {
synchronized(Hoge.class) { //<-HERE ! change "Hoge.class" into "this".
fuga = str;
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
String getStr(String suffix) {
synchronized(Hoge.class) {
return suffix+ fuga;
}
}
}
答案 0 :(得分:2)
由于this
和gh
中的gh2
不同,this
是Hoge的一个实例。
因此,当使用Hoge.class
时,只有一个同步锁,而不是使用this
,它将使用两个不同的锁。
答案 1 :(得分:2)
您的setStr
方法应该是这样的:
public void setStr(String str) {
synchronized(Hoge.class) { //<-HERE ! change "Hoge.class" into "this".
fuga = str;
try {
Hoge.class.wait();//call wait on Hoge.class
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
您应该使用Hoge.clas.wait()
代替wait()
。为什么呢?
因为,正如oracle documentation about wait():
此方法只应由作为其所有者的线程调用 这个对象的监视器。
即thread can't invoke a wait on an object until it owns that object's lock
。否则它将抛出IllegalMonitorStateException
。在这里,您正在获取对Class
Hoge(即Hoge.class)的对象的锁定,称为class level lock
,但是在wait
的当前对象上调用Hoge
({ {1}})。所以它导致this
。这就是为什么当您获取当前对象(IllegalMonitorStateException
)上的锁时,您的代码工作正常,因为在这种情况下this
在当前对象(wait()
)本身上被调用。