user1079065
user1079065

Reputation: 2205

Why to use wait method on strings or other objects?

I have following piece of code:

synchronized void myMethod() {
  String s="aaa";
  try {
    s.wait();
  } catch (InterruptedException e) {
    e.printStackTrace();
  }
}

The code throws exception ... I have seen codes using wait method on threads which is self explainable and logical..

  1. why would one use wait method on an object like string instead of using it on main thread?
  2. what is its use?
  3. are there any practical implementations like this?

Thanks in advance

Upvotes: 2

Views: 1568

Answers (4)

Nathan Hughes
Nathan Hughes

Reputation: 96394

Your sample code won't work because the method is synchronizing on the instance that myMethod is called on, while the wait is called on the string. It will cause an IllegalMonitorStateException. You have to call wait and notify on the same object that you're locking on. The threads that get notified are the ones waiting on the lock that notify is called on.

Locking on a string object is a bad idea, don't do it. You don't want to lock on things where you can't reason about who can acquire them because anybody could acquire them. Some other code elsewhere in the application could be locking on the same string value, and you'd have the potential for strange interactions, deadlocking because the other code was taking your lock, or have the other code notifying you. Do you want to have to think about how strings are pooled when debugging some multithreading behavior?

You can limit who can acquire your lock by defining your own lock and making it private, like this:

private final Object LOCK = new Object();

so only threads calling the methods of the object you're controlling access to can acquire the lock:

public void myMethod() {
   synchronized(LOCK) {
      ...
   }
}

That way you know exactly what can acquire the lock, it's not available to every thread in the application. The lock can be acquired by anything that can get a reference to that object, so keep the reference private.

The way your example uses wait without a loop with a condition variable is very suspect. A thread can exit from a call to wait without having been notified. Even if a thread is notified, that doesn't give it any special priority with the scheduler. Another thread can barge in and do something, possibly something affecting the state that the notification was alerting the waiting thread to, between the time the thread is notified and the time that the thread can reacquire the lock it gave up when it started waiting. For both reasons there needs to be a loop where the thread retests a condition when it wakes from waiting.

Also if by "codes using wait method on threads" you mean code where a Thread object is used as a lock, that's another thing to avoid doing, see the API documentation for Thread#join:

This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

Upvotes: 8

user2982130
user2982130

Reputation:

This is an example of synchronization with no affect.

First of all, it is unlikely you will need to synchronize on String, it is immutable after all, therefore, you don't need it to perform anything asynchronously.

Second, you are likely to be synchronizing on the incorrect object anyways, no correctly written program would use String as a synchronization lock.

Third and finally, s is a local variable. In fact, it holds exactly the same pattern that JCIP specifically tells you not to use if you inline it:

synchronized (new Object()) {
    // ...
}

This is synchronization without effect, as it does not guarantee the purpose of the synchronized keyword: serialized access, lock and release semantics that require that only one thread execute the synchronized block at any given time.

Because of this, each thread will have their own lock - not good.

Upvotes: 0

Dima
Dima

Reputation: 8652

wait() method is implemented in Object, and String extends object so it can be used. why someone use it? ask him. its not a programming question.

something i can think of:

he could be using "lock1".wait() in one class and "lock1".notify() in other, it will be something like global lock object because literals are interned by the compiler and thus refer to the same object but its VERY VERY BAD PRACTICE

Upvotes: 4

Smith_61
Smith_61

Reputation: 2088

You first need to be synchronized on the Object before calling wait. This is where you are getting the exception from.

void test() {
    String s = "AAA";
    synchronized( s ) {
        s.wait();
    }
}

The same thing must be done when you call notify, but in this case it is a very very bad idea because if a thread enters this method it will never return. Although considering it is a String literal you may be able to get away with it by using the same literal in another method in the same class, but don't count on it.

Upvotes: 4

Related Questions