IllegalMonitorStateException 尽管从同步上下文调用 notifyAll()
IllegalMonitorStateException despite calling notifyAll() from synchronised context
public class Alternate {
static Boolean mutex = true;
public static void main(String[] args) {
Thread t1 = new Thread(new Odd(mutex));
Thread t2 = new Thread(new Even(mutex));
t1.start();
t2.start();
}
}
class Odd implements Runnable{
Boolean mutex;
Odd( Boolean mutex){
this.mutex=mutex;
}
@Override
public void run() {
try {
synchronized(mutex){
while(mutex){
mutex.wait();
}
System.out.println("odd");
mutex=true;
mutex.notifyAll();
Thread.sleep(500);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Even implements Runnable{
Boolean mutex;
Even( Boolean mutex){
this.mutex=mutex;
}
@Override
public void run() {
try {
synchronized(mutex){
while(!mutex){
mutex.wait();
}
System.out.println("even");
mutex=false;
mutex.notifyAll();
Thread.sleep(500);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
错误是
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at com.test.concurrency.Even.run(Alternate.java:55)
at java.lang.Thread.run(Thread.java:722)
我无法找出错误的原因。我从同步上下文调用 notifyAll() 并从正确的对象调用它。
您正在从线程下更改锁定。每次将布尔值设置为某个东西时,它就是一个不同的对象;代码
mutex=true;
mutex.notifyAll();
将 mutex 设置为与线程同步的对象不同的对象(因此线程尚未为其获取监视器),然后在新对象上调用 notifyAll。
使用单锁,不要更改。
锁定布尔值、数字包装器或字符串太容易出错,应该避免。不仅您最终会遇到您所看到的错误,而且应用程序的其他不相关部分(可能是由其他人按照相同的做法编写的)可能锁定在同一个对象上并导致神秘的问题。布尔值、数字包装器和字符串可用于 JVM 中的所有内容。最好使用范围受限的锁,这样您的应用程序中的其他任何东西都无法获取它。
通常最好使用专用锁,不要将其用于任何其他目的。超载不同用途的东西很容易造成麻烦。
如果有人需要,请更正代码
import java.util.concurrent.atomic.AtomicInteger;
public class Alternate {
static final AtomicInteger mutex = new AtomicInteger(0);
public static void main(String[] args) {
Thread t1 = new Thread(new Odd());
Thread t2 = new Thread(new Even());
t1.start();
t2.start();
}
static class Odd implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
synchronized(mutex){
while(mutex.get()==1){
mutex.wait();
}
System.out.println("odd");
mutex.compareAndSet(0, 1);
mutex.notifyAll();
}
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Even implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
synchronized(mutex){
while(mutex.get()==0){
mutex.wait();
}
System.out.println("even");
mutex.compareAndSet(1, 0);
mutex.notifyAll();
}
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Alternate {
static Boolean mutex = true;
public static void main(String[] args) {
Thread t1 = new Thread(new Odd(mutex));
Thread t2 = new Thread(new Even(mutex));
t1.start();
t2.start();
}
}
class Odd implements Runnable{
Boolean mutex;
Odd( Boolean mutex){
this.mutex=mutex;
}
@Override
public void run() {
try {
synchronized(mutex){
while(mutex){
mutex.wait();
}
System.out.println("odd");
mutex=true;
mutex.notifyAll();
Thread.sleep(500);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class Even implements Runnable{
Boolean mutex;
Even( Boolean mutex){
this.mutex=mutex;
}
@Override
public void run() {
try {
synchronized(mutex){
while(!mutex){
mutex.wait();
}
System.out.println("even");
mutex=false;
mutex.notifyAll();
Thread.sleep(500);
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
错误是
java.lang.IllegalMonitorStateException
at java.lang.Object.notifyAll(Native Method)
at com.test.concurrency.Even.run(Alternate.java:55)
at java.lang.Thread.run(Thread.java:722)
我无法找出错误的原因。我从同步上下文调用 notifyAll() 并从正确的对象调用它。
您正在从线程下更改锁定。每次将布尔值设置为某个东西时,它就是一个不同的对象;代码
mutex=true;
mutex.notifyAll();
将 mutex 设置为与线程同步的对象不同的对象(因此线程尚未为其获取监视器),然后在新对象上调用 notifyAll。
使用单锁,不要更改。
锁定布尔值、数字包装器或字符串太容易出错,应该避免。不仅您最终会遇到您所看到的错误,而且应用程序的其他不相关部分(可能是由其他人按照相同的做法编写的)可能锁定在同一个对象上并导致神秘的问题。布尔值、数字包装器和字符串可用于 JVM 中的所有内容。最好使用范围受限的锁,这样您的应用程序中的其他任何东西都无法获取它。
通常最好使用专用锁,不要将其用于任何其他目的。超载不同用途的东西很容易造成麻烦。
如果有人需要,请更正代码
import java.util.concurrent.atomic.AtomicInteger;
public class Alternate {
static final AtomicInteger mutex = new AtomicInteger(0);
public static void main(String[] args) {
Thread t1 = new Thread(new Odd());
Thread t2 = new Thread(new Even());
t1.start();
t2.start();
}
static class Odd implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
synchronized(mutex){
while(mutex.get()==1){
mutex.wait();
}
System.out.println("odd");
mutex.compareAndSet(0, 1);
mutex.notifyAll();
}
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
static class Even implements Runnable{
@Override
public void run() {
try {
for(int i=0;i<10;i++){
synchronized(mutex){
while(mutex.get()==0){
mutex.wait();
}
System.out.println("even");
mutex.compareAndSet(1, 0);
mutex.notifyAll();
}
}
}catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}