The modern way of suspending, resuming, and stopping threads and multiple threads on multiple instances?

After reading considerable stuff regarding threads on the net and with help from Herbert Schildt book, The Complete Refernce Java, I know that

synchronized only prevents multiple threads from simultaneously executing the method in the same
instance. I said... in the same instance.

When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object. Notice ... in the same instance(object).

Thirdly, from oracle docs,
when a synchronized method exits, it automatically establishes a happens-before RELATIONSHIP with any subsequent invocation of a synchronized method for the same object. This guarantees that
changes to the state of the object are visible to all threads. This also involves working on the same object with multiple threads.

But when the situation comes to Multiple threads working on different instances of the same class, I am getting overall confused and not able to make out what's happening and how is it happening?

Consider the example given in the Herbert Schildt book: Suspending and resuming a thread the modern way.

class NewThread implements Runnable {

String name; // name of thread
Thread t;
boolean suspendFlag;

NewThread(String threadname) {
    name = threadname;
    t = new Thread(this, name);
    System.out.println("New thread: " + t);
    suspendFlag = false;
    t.start(); // Start the thread
}

// This is the entry point for thread.
public void run() {
    try {
        for (int i = 15; i > 0; i--) {
            System.out.println(name + ": " + i);
            Thread.sleep(2000);
            synchronized (this) {
                while (suspendFlag) {
                    wait();
                }
            }
        }
    } catch (InterruptedException e) {
        System.out.println(name + " interrupted.");
    }
    System.out.println(name + " exiting.");
}

void mysuspend() {
    suspendFlag = true;
}

synchronized void myresume() {
    suspendFlag = false;
    notify();
}
}

The main thread :

class SuspendResume {

public static void main(String args[]) {

    NewThread ob1 = new NewThread("One");
    NewThread ob2 = new NewThread("Two");

    try {
        Thread.sleep(10000);
        ob1.mysuspend();
        System.out.println("Suspending thread One");

        Thread.sleep(10000);
        ob1.myresume();
        System.out.println("Resuming thread One");

        ob2.mysuspend();
        System.out.println("Suspending thread Two");
        Thread.sleep(10000);

        ob2.myresume();
        System.out.println("Resuming thread Two");
    } catch (InterruptedException e) {
        System.out.println("Main thread Interrupted");
    }
    // wait for threads to finish
    try {
        System.out.println("Waiting for threads to finish.");
        ob1.t.join();
        ob2.t.join();
    } catch (InterruptedException e) {
        System.out.println("Main thread Interrupted");
    }

    System.out.println("Main thread exiting.");
}

}

the output is as follows:

New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
One: 15
Two: 15
One: 14
Two: 14
Two: 13
One: 13
Two: 12
One: 12
Two: 11
One: 11
Suspending thread One
Two: 10
Two: 9
Two: 8
Two: 7
Two: 6
Resuming thread One
Suspending thread Two
One: 10
One: 9
One: 8
One: 7
One: 6
Resuming thread Two
Waiting for threads to finish.
Two: 5
One: 5
Two: 4
One: 4
Two: 3
One: 3
Two: 2
One: 2
Two: 1
One: 1
Two exiting.
One exiting.
Main thread exiting.

My understanding: There are 3 threads. Other than the main thread, 2 are working on 2 instances of the same class.

Main thread goes to sleep for 10 seconds. During this time period, the 2 other are able to make 5 times through the for loop.(Since they too get to sleep for 2 seconds each.) The flag was false during this interval and as such they didn't go the while loop.The o/p during this interval is :

One: 15
Two: 15
One: 14
Two: 14
Two: 13
One: 13
Two: 12
One: 12
Two: 11
One: 11

Main thread wakes up.

ob1 calls it mysuspend() which changes the suspendFlag to true. Confused here: will this change be taken into consideration by thread working ob1.

Suspending thread One //this gets print.

Main thread goes to sleep again for 10 seconds. the thread working on ob1 didn't produce any output. WHY? (Because the change previously mentioned was taken into consideration and that's why after going through the loop, wait() suspends this thread. Am I correct?).

Two: 10
Two: 9
Two: 8
Two: 7
Two: 6

ob1 calls the synchronised method: myresume() within which it changes

suspendFlag to false and

issues a notify() // notification to the other thread working on the other object. I know for sure A notify command selects one thread arbitrarily from the wait set and marks it for eventual resurrection. and the lock is still with it.

Confused here: How was the thread (on ob1) able to resurrect itself(I mean how come by just changing the flag even though i am not too clear how it got suspended.)

Resuming thread One // gets printed. the thread was clearly resurrected(resume) since the o/p is there as shown below.

One: 10
One: 9
One: 8
One: 7
One: 6

During the same time, the other thread got suspended and same thing happened.

One more question:

When one thread is executing a synchronized method for an object, does all other threads that invoke synchronized methods for the other object block (suspend execution) until the first thread is done with the object. I said the other object?

Upvotes: 2

Views: 381

Answers (1)

BatScream
BatScream

Reputation: 19700

ob1 calls it mysuspend() which changes the suspendFlag to true. Confused here: will this change be taken into consideration by thread working ob1.

Main thread goes to sleep again for 10 seconds. the thread working on ob1 didn't produce any output. WHY? (Because the change previously mentioned was taken into consideration and that's why after going through the loop, wait() suspends this thread. Am I correct?).

Yes. Since the state of the runnable instance 'ob1' has changed, and will affect only the Thread working on the runnable instance 'ob1'.

issues a notify() // notification to the other thread working on the other object.

No. The java.lang.Object.notify() wakes up a single thread that is waiting on this object's monitor. Note the keyword this. Since ob1 has only one thread acting upon it, the thread which issued wait(), will be notified, not the thread working on ob2, they are two different threads working on two different runnable instances of the same type.

How was the thread (on ob1) able to resurrect itself(I mean how come by just changing the flag even though i am not too clear how it got suspended.)

The thread bound to ob1 can monitor the changes in the state of ob1. The thread bound to ob2 can monitor the changes in the state of ob2.

When one thread is executing a synchronized method for an object, does all other threads that invoke synchronized methods for the other object block (suspend execution) until the first thread is done with the object. I said the other object?

No. Only the threads working on that particular instance get affected. If you want that to happen,

NewThread obj = new NewThread(); // single runnable instance
Thread ob1 = new Thread(obj); // two different threads sharing the same instance
Thread ob2 = new Thread(obj);

This way Threads ob1 and ob2 can share the obj instance and communicate with each other using wait() and notify() methods of obj.

If you are looking for synchronizing threads across instances, then look into:this.

Upvotes: 1

Related Questions