当我尝试运行以下程序时,在这段代码中第一次调用notify()时会出现IllegalMonitorStateException:
synchronized (c) {
try {
notify();
....
这让我有点失望:当代码已经在同步块中时,如果对象(c)检查相同的锁,代码怎么可能没有锁定?
请不要介意有些奇怪的过度使用notify()和wait()。我知道有不同的(并且更有效的)实现可以执行相同的任务,但是现在我正在试图弄清楚为什么这个特定的不起作用。
完整代码如下:
class J implements Runnable {
public static void main(String[] x) {
Calc calc = new Calc();
J j = new J(calc);
Thread t1 = new Thread(j, "one");
Thread tCalc = new Thread(calc, "Calc");
tCalc.start();
t1.start();
}
Calc c;
public J(Calc c) {
this.c = c;
}
public void run() {
synchronized (c) {
try {
notify();
c.wait();
} catch (InterruptedException e) {
}
System.out.println(Thread.currentThread().getName() + ": x = "
+ c.getX());
notify();
}
}
}
class Calc implements Runnable {
private int x;
public int getX() {
return x;
}
public void run() {
synchronized (this) {
for (int x = 1; x <= 11111; x *= (x + x)) {
this.x += x;
try {
notify();
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
notify();
}
}
}
答案 0 :(得分:3)
您正在尝试通知等待您当前未持有的其他锁的线程。 错误是合理的。您对对象c进行了锁定,然后通知其他线程有关当前对象的锁定。
答案 1 :(得分:1)
synchronized (c) {
try {
notify();
....
您正在锁定对象c
,但您正在通知对象this
。最好始终明确指定您明确指定哪个对象wait()
或notify()
。你应该这样做:
synchronized (c) {
try {
c.notify();
....
或:
synchronized (this) {
try {
this.notify();
....
看起来你实际上意味着处理2个锁。如果是这种情况,那么你会做类似以下的事情。
synchronized (c) {
try {
synchronized (this) {
this.notify();
}
c.wait();
确保始终首先锁定c
,然后this
,这一点非常重要,否则您将陷入僵局。
答案 2 :(得分:0)
你所拥有的是一种复杂的做法。
ExecutorService printer = Executors.newSingleThreadExecutor();
int x2 = 0;
for (int x = 1; x <= 11111; x *= (x + x)) {
x2 += x;
final int x3 = x2;
printer.submit(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + ": x = " + x3);
}
});
}
printer.shutdown();
如果您没有尝试使用两个线程来执行更快/更简单的操作,那么这将更加简单。