java - IllegalMonitorStateException when use .class as monitor while "this" not
问题描述
I just wrote a program to print 0-99 using two threads by turns. I use synchronized block to finish the job. In my code, when I use "this" as synchronized monitor, the program works well. But when I use ".class" as synchronized monitor, I got IllegalMonitorStateException
. Can anyone tell what happened?
Here's my code which works well
public class WaitTest implements Runnable {
private int n = 0;
@Override
public void run() {
while (true) {
synchronized (this){
notify();
if (n < 100) {
System.out.println(Thread.currentThread().getName() + " " + Integer.toString(n));
++n;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else
break;
}
}
}
public static void main(String[] args) {
WaitTest waitTest = new WaitTest();
Thread threadA = new Thread(waitTest);
Thread threadB = new Thread(waitTest);
threadA.start();
threadB.start();
}
}
Here's my code which I got an Exception
public class WaitTest implements Runnable {
private int n = 0;
@Override
public void run() {
while (true) {
synchronized (WaitTest.class){
notify();
if (n < 100) {
System.out.println(Thread.currentThread().getName() + " " + Integer.toString(n));
++n;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else
break;
}
}
}
public static void main(String[] args) {
WaitTest waitTest = new WaitTest();
Thread threadA = new Thread(waitTest);
Thread threadB = new Thread(waitTest);
threadA.start();
threadB.start();
}
}
The only difference between them is the content in the brace after synchronized
解决方案
In my code, when I use "this" as synchronized monitor, the program works well.
That is because when you call the methods wait()
and notify()
you are implicitly calling them from the instance return by this
, which matches the object used in the your synchronized clause (i.e., synchronized (this)
).
But when I use ".class" as synchronized monitor, I got IllegalMonitorStateException.
This happens because you synchronized on the WaitTest.class
class but you call the wait
and notify
methods again for the this
instance. Therefore, to avoid that exception change the calls of wait(); and notify();
to WaitTest.class.wait();
and WaitTest.class.notify();
, respectively.
The code fixed:
public class WaitTest implements Runnable {
private int n = 0;
@Override
public void run() {
while (true) {
synchronized (WaitTest.class){
WaitTest.class.notify();
if (n < 100) {
System.out.println(Thread.currentThread().getName() + " " + Integer.toString(n));
++n;
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
WaitTest.class.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else
break;
}
}
}
public static void main(String[] args) {
WaitTest waitTest = new WaitTest();
Thread threadA = new Thread(waitTest);
Thread threadB = new Thread(waitTest);
threadA.start();
threadB.start();
}
}
推荐阅读
- sql - Oracle 运行减法
- php - 如何从变量中获取部分字符串值
- python - 我想迭代一个循环并计算总时间直到条件持续否则总时间直到条件在python中不持续
- python-3.x - 如果不同数据集中不存在,熊猫会创建多个列(数据集是字典的值)
- web - 有没有免费的网站可以把通话录音转换成文字?
- javascript - Hugo 在帖子中使用内联 javascript
- javascript - React webpack 错误:您可能需要适当的加载器来处理此文件类型,目前没有配置加载器来处理此文件
- python - 在 django 中使用 pandas to_sql 时数据库模式发生变化
- angular - 使用 ng2-charts 创建一个图表并给它一个可观察的标签
- javascript - 如何将图像/徽标放在中间位置