我对多线程的了解很少。
我希望在程序之下能够完美地运行,但它不能正常运行并产生以下异常。
Exception in thread "Thread-1" java.lang.IllegalMonitorStateException
at java.lang.Object.notify(Native Method)
at com.onmobile.client.D.callD(Deadlock.java:76)
at com.onmobile.client.B.run(Deadlock.java:50)
at java.lang.Thread.run(Unknown Source)
Java文件
public class Deadlock {
C c = new C();
D d = new D();
public static void main(String[] args) {
new Deadlock();
}
public Deadlock() {
A a = new A(d,c);
B b = new B(d,c);
Thread t1 = new Thread(a);
Thread t2 = new Thread(b);
t1.start();
t2.start();
}
}
class A implements Runnable{
D dObj;
C cObj;
A(D obj, C obj1){
this.dObj = obj;
this.cObj = obj1;
}
@Override
public void run() {
cObj.callC(dObj);
}
}
class B implements Runnable{
D dObj;
C cObj;
B(D obj, C obj1){
this.dObj = obj;
this.cObj = obj1;
}
@Override
public void run() {
dObj.callD(cObj);
}
}
class C{
public synchronized void callC(D dObj){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
dObj.callD1();
}
public synchronized void callC1(){
}
}
class D{
public synchronized void callD(C cObj){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cObj.callC1();
cObj.notify();
}
public synchronized void callD1(){
}
}
我认为在callC()方法中,C类的对象即cObj进入等待状态,同时控制将转到callD()方法并在那里调用cObj.notify(); 因此,这将唤醒等待对象cObj的等待线程。
但它给了我例外。 我认为我的问题的解决方案可以是: Java: IllegalMonitorStateException on notify()
但我不能正确理解它。
请指导我出错的地方。
答案 0 :(得分:4)
当调用object.notify时,你必须持有该确切对象的锁,即:
synchronized(cObj) {
cObj.notify();
}
你还应该在类似的同步块中包装你的等待呼叫:
synchronized(cObj) {
cObj.wait()
}
我建议您在Java教程中阅读更多相关内容: http://docs.oracle.com/javase/tutorial/essential/concurrency/
答案 1 :(得分:0)
如果您想要通知或等待某个对象,您的线程必须拥有您所操作对象的监视器。
public synchronized void callD(C cObj){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
cObj.callC1();
cObj.notify();
}
在此代码部分中,您将同步类D
的实例,因为同步方法始终获取它们“活动”的对象的监视器。但是,为了能够使用cObj.notify()
,您必须获取cObj
实例的监视器,例如通过做
synchronized(cObj) {
cObj.notify();
}
答案 2 :(得分:0)
notify
上的Object
只有在对该对象进行锁定或synchronizing
后才能调用。所以在你的情况下你需要的是:
class D{
public void callD(C cObj){ //synchronized not required here
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronize(cObj) { //synchornize here on cObj
cObj.callC1();
cObj.notify();
}
}
}
注意:如果您将代码更改为synchornize callD
和synchroniz(cObj)
,请确保您处于deadlock
方案。恕我直言只有synchroniz(cObj)
就足够了。
答案 3 :(得分:0)
要在对象上调用notify()
,您需要拥有此对象的锁定。在这种情况下调用
cObj.notify();
你需要将它包装成同步块,如下所示:
syncronized (cObj)
{
cObj.notify();
}