new Thread(() -> {
synchronized (ReleaseLockDemo.class) {
System.out.printf("线程[%s]进入1号\n", Thread.currentThread().getName());
try {
// Thread.sleep(1000);
Thread.currentThread().wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("线程【%s】退出1号\n", Thread.currentThread().getName());
}
}).start();
new Thread(() -> {
synchronized (ReleaseLockDemo.class) {
System.out.printf("线程[%s] 进入2号\n", Thread.currentThread().getName());
System.out.printf("线程【%s】退出2号\n", Thread.currentThread().getName());
}
}).start();
线程[Thread-0]进入1号
Exception in thread "Thread-0" 线程[Thread-1] 进入2号
线程【Thread-1】退出2号
java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.concurrency.ReleaseLockDemo.lambda$main$0(ReleaseLockDemo.java:17)
at java.lang.Thread.run(Thread.java:748)
为什么会是这样的结果呢?按道理来说, 应该是下面这个结果才对呀。它为什么会在1号线程等待的时候,2号线程运行了呢,它不应该是要等待1号线线程中的锁释放了才能运行的吗?又为什么会报两个错呢?
线程[Thread-0]进入1号
线程【Thread-0】退出1号
线程[Thread-1] 进入2号
线程【Thread-1】退出2号
那我们先总结下问题:
Exception in thread "Thread-0"
错java.lang.IllegalMonitorStateException
错那么带着问题我们来分析下这段代码。
ReleaseLockDemo.class
,在两个同步代码块中,用同一个锁,一个代码块运行了,而另一个要运行的话,只有前面的锁释放了后面的代码块才能正常运行。可是在前面的1号线程只运行到了一半就直接运行2号线程了,中间只做了一个wait
操作,难道wait
操作会引发锁的释放吗?wait()
方法时,monitor被释放了,并且进入休眠状态,然后唤醒其他的线程(可能一个或多个),此时其他线程是可以重新获取到该monitor object的。IllegalMonitorStateException
, 这是一个monitor报错synchronized(this)
),而这个对象就是monitor object。java.lang.IllegalMonitorStateException
wait()
方法必须要用拥有该对象monitor的线程才可以正常调用,而我们的代码中synchronzed所锁住的对象是ReleaseLockDemo.class
。因此,执行该程序后报java.lang.IllegalMonitorStateException
错误。Exception in thread "Thread-0"
错,这个错跟后面的IllegalMonitorStateException
是同一个错,只是因为当时线程休眠了,没有执行完而已。wait()
方法那么如果我们把monitor object换成当前类的对象会不会就不会报错了呢?public static void main(String[] args) {
WaitMethodTest wmt = new WaitMethodTest();
wmt.run1();
wmt.run2();
}
private void run2() {
new Thread(() -> {
synchronized (this) {
System.out.printf("线程[%s] 进入2号\n", Thread.currentThread().getName());
System.out.printf("线程【%s】退出2号\n", Thread.currentThread().getName());
}
}).start();
}
private void run1() {
new Thread(() -> {
synchronized (this) {
System.out.printf("线程[%s]进入1号\n", Thread.currentThread().getName());
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("线程【%s】退出1号\n", Thread.currentThread().getName());
}
}).start();
}
线程Thread-0进入1号
线程Thread-1 进入2号
线程【Thread-1】退出2号
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。