编程语言
首页 > 编程语言> > Java同步的字符串IllegalMonitorStateException

Java同步的字符串IllegalMonitorStateException

作者:互联网

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

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()外,StackTrace中什么也没有.

解决方法:

>您的代码包含数据争用,因为它访问同步块外部的可变字符串变量.具体来说,这发生在synced(string)行上.当取消引用字符串以到达其监视器将被锁定的对象时,线程尚未对该对象持有锁定.因此,您无法保证它将锁定哪个对象.
>更改字符串变量的事实意味着它现在指向其他对象.当下一个线程获得对该新对象的锁定时,它将不会从任何之前发生的关系中受益,因为它是有史以来第一个获得对其锁定的线程.也不保证相互排斥,因为可能有任意多个线程,每个线程锁定一个不同的String实例而没有争用.
>结合上述两种现象,我们还可以看到,不能保证在synced(string)行上到达的对象将与从synced块内到达的对象相同.一旦碰巧这确实是一个不同的对象,就会发生IllegalMonitorStateException.

总之,情况与根本不存在的同步块非常相似.

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

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,multithreading,blackberry
来源: https://codeday.me/bug/20191013/1906512.html