Java同步的字符串IllegalMonitorStateException [英] Java synchronized String IllegalMonitorStateException

查看:239
本文介绍了Java同步的字符串IllegalMonitorStateException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让Thread2等待String和Thread1通知String更新,我确实同步了String对象,如下面的代码所示,但是我仍然得到IllegalMonitorStateException这是我的代码

I'm trying to have a Thread2 wait for a String and Thread1 to notify on String update, I do synchronize The String object as code below shows, But I still get IllegalMonitorStateException Here's my code

public class Class1{

String string   = "";

public Class1(){


    Thread t1   = new Thread(){

        public void run(){

            synchronized(string){

                string = "Something"; string.notifyAll();   //This is the line that throws an IllegalMonitorStateException
            }

        }

    };


    Thread t2   = new Thread(){

        public void run(){

            synchronized(string){

                try{

                    string.wait();

                }catch(Exception e){

                    e.printStackTrace();

                }

            }

        }

    };

    t2.start();
    t1.start();
}

}

除了突出显示string.notifyAll()

推荐答案

  1. 您的代码包含一个数据竞争,因为它访问了synchronized块之外的可变string变量.具体来说,这发生在行synchronized(string)上.在取消引用string以到达其监视器将被锁定的对象时,线程尚未对该对象持有锁定.因此,您无法保证它将锁定哪个对象.

  1. Your code contains a data race because it accesses the mutable string variable outside of a synchronized block. Specifically, this happens on the line synchronized(string). While dereferencing string to reach the object whose monitor will be locked, the thread does not already hold a lock on that object. Therefore you have no guarantee which object it will acquire a lock on.

您对string变量进行了变异的事实意味着,该变量现在指向其他对象.当下一个线程获得对该新对象的锁定时,它将不会从任何 happens-before 关系中受益,因为它是第一个获得该锁定的线程.也不能保证互斥,因为可能有任意多个线程,每个线程锁定一个不同的String实例而没有争用.

The fact that you mutate the string variable means that it now points to some other object. When the next thread acquires a lock on that new object, it will not benefit from any happens-before relationship because it is the first thread to ever acquire a lock on it. Mutual exclusion will not be guaranteed, either, because there may be arbitrarily many threads, each locking a different String instance without contention.

结合上述两种现象,我们还可以看到,不能保证在行synchronized(string)上到达的对象将与在到达的对象相同.同步块.一旦碰巧这确实是一个不同的对象,您的IllegalMonitorStateException就会随之发生.

Combining the two phenomena described above we can also see that there is no guarantee that the object reached on the line synchronized(string) will be the same one as the one reached from within the synchronized block. Once it happens that this is indeed a different object, your IllegalMonitorStateException ensues.

总而言之,情况与根本不存在的synchronized块非常相似.

In summary, the situation is very similar to the synchronized block not existing at all.

如果您坚持使用专用的final变量来引用用于锁定的对象的最佳实践,则可以避免上述所有问题.简而言之,并修复示例中的编译错误,这是您必须编写的:

All of the above problems can be avoided if you keep to the best practice of using dedicated final variables to refer to objects used for locking. In a nutshell, and fixing the compilation errors in your example, this is what you would have to write:

static String string = "";
static final Object lock = new Object();

public static void main(String[] args) {
  Thread t1 = new Thread() {
    public void run() {
      synchronized (lock) {
        ... update the string variable ...
        lock.notifyAll();
      }
    }
  };
  Thread t2 = new Thread() {
    public void run() {
      synchronized (lock) {
        try {
          lock.wait();
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  };
  t2.start();
  t1.start();
}

这篇关于Java同步的字符串IllegalMonitorStateException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆