Java synchronized String IllegalMonitorStateException

后端 未结 1 1948
闹比i
闹比i 2021-01-27 04:15

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 IllegalMoni

相关标签:
1条回答
  • 2021-01-27 04:47
    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.

    2. 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.

    3. 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.

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

    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();
    }
    
    0 讨论(0)
提交回复
热议问题