谁能解释为什么这个程序显示 IllegalMonitorStateException?
Can anybody explain why this program is showing an IllegalMonitorStateException?
class Lock
{
public int l=0;
}
class Numbers extends Thread
{
final Lock lock;
Numbers(Lock l,String name)
{
super(name);
lock=l;
}
public void run()
{
synchronized(lock)
{
for(int i=0;i<100;i++)
{
if(i==50)
{
try
{
while(lock.l==0)
{
System.out.println("Waiting for letters to complete");
wait();
System.out.println("Wait complete");
}
}
catch(InterruptedException e)
{
System.err.println("ERROR");
}
}
System.out.println(i);
}
}
}
}
class Letters extends Thread
{
final Lock lock;
Letters(Lock l,String name)
{
super(name);
lock=l;
}
public void run()
{
synchronized(lock)
{
for(int i=65;i<=90;i++)
System.out.println((char)i);
lock.l=1;
notify();
}
}
}
public class MyClass
{
public static void main(String args[])
{
Lock l=new Lock();
Numbers n=new Numbers(l,"Numbers");
Letters let=new Letters(l,"Letters");
n.start();
let.start();
}
}
我打算通过这个程序打印最多 49 的数字,然后等待 Letters 线程完成打印字母,然后控件返回 Numbers 线程并完成执行。
但是此代码在打印最多 49 个数字然后打印 A-Z 之后抛出异常,然后执行失败显示 IllegalMonitorStateException。
fails to execute showing IllegalMonitorStateException.
这是因为对 notify();
方法的调用不遵守其 contract:
Wakes up a single thread that is waiting on this object's monitor.
(...)
This method should only be called by a thread that is the owner of
this object's monitor.
同样适用于wait
方法:
This method should only be called by a thread that is the owner of this object's monitor.
TL:DR
您在错误的 lock 上调用 wait
和 notify()
(即 实例 return 的隐式 锁 this
).
分别将这些调用更改为:
lock.notify();
和 lock.wait();
运行 基于您的代码的示例:
class Lock{
public int l=0;
}
class Numbers extends Thread
{
final Lock lock;
Numbers(Lock l,String name){
super(name);
lock=l;
}
public void run() {
synchronized(lock) {
for(int i=0;i<100;i++){
if(i==50){
try {
while(lock.l==0){
System.out.println("Waiting for letters to complete");
lock.wait();
System.out.println("Wait complete");
}
}
catch(InterruptedException e){
System.err.println("ERROR");
}
}
System.out.println(i);
}
}
}
}
class Letters extends Thread {
final Lock lock;
Letters(Lock l,String name)
{
super(name);
lock=l;
}
public void run()
{
synchronized(lock){
for(int i=65;i<=90;i++)
System.out.println((char)i);
lock.l=1;
lock.notify();
}
}
}
class MyClass {
public static void main(String args[]) {
Lock l=new Lock();
Numbers n=new Numbers(l,"Numbers");
Letters let=new Letters(l,"Letters");
n.start();
let.start();
}
}
class Lock
{
public int l=0;
}
class Numbers extends Thread
{
final Lock lock;
Numbers(Lock l,String name)
{
super(name);
lock=l;
}
public void run()
{
synchronized(lock)
{
for(int i=0;i<100;i++)
{
if(i==50)
{
try
{
while(lock.l==0)
{
System.out.println("Waiting for letters to complete");
wait();
System.out.println("Wait complete");
}
}
catch(InterruptedException e)
{
System.err.println("ERROR");
}
}
System.out.println(i);
}
}
}
}
class Letters extends Thread
{
final Lock lock;
Letters(Lock l,String name)
{
super(name);
lock=l;
}
public void run()
{
synchronized(lock)
{
for(int i=65;i<=90;i++)
System.out.println((char)i);
lock.l=1;
notify();
}
}
}
public class MyClass
{
public static void main(String args[])
{
Lock l=new Lock();
Numbers n=new Numbers(l,"Numbers");
Letters let=new Letters(l,"Letters");
n.start();
let.start();
}
}
我打算通过这个程序打印最多 49 的数字,然后等待 Letters 线程完成打印字母,然后控件返回 Numbers 线程并完成执行。
但是此代码在打印最多 49 个数字然后打印 A-Z 之后抛出异常,然后执行失败显示 IllegalMonitorStateException。
fails to execute showing IllegalMonitorStateException.
这是因为对 notify();
方法的调用不遵守其 contract:
Wakes up a single thread that is waiting on this object's monitor. (...) This method should only be called by a thread that is the owner of this object's monitor.
同样适用于wait
方法:
This method should only be called by a thread that is the owner of this object's monitor.
TL:DR
您在错误的 lock 上调用 wait
和 notify()
(即 实例 return 的隐式 锁 this
).
分别将这些调用更改为:
lock.notify();
和 lock.wait();
运行 基于您的代码的示例:
class Lock{
public int l=0;
}
class Numbers extends Thread
{
final Lock lock;
Numbers(Lock l,String name){
super(name);
lock=l;
}
public void run() {
synchronized(lock) {
for(int i=0;i<100;i++){
if(i==50){
try {
while(lock.l==0){
System.out.println("Waiting for letters to complete");
lock.wait();
System.out.println("Wait complete");
}
}
catch(InterruptedException e){
System.err.println("ERROR");
}
}
System.out.println(i);
}
}
}
}
class Letters extends Thread {
final Lock lock;
Letters(Lock l,String name)
{
super(name);
lock=l;
}
public void run()
{
synchronized(lock){
for(int i=65;i<=90;i++)
System.out.println((char)i);
lock.l=1;
lock.notify();
}
}
}
class MyClass {
public static void main(String args[]) {
Lock l=new Lock();
Numbers n=new Numbers(l,"Numbers");
Letters let=new Letters(l,"Letters");
n.start();
let.start();
}
}