0

I'm learning Thread in java.

The following example shows how to suspend, resume and stop threads:

class MyNewThread implements Runnable {
Thread thrd;

boolean suspended;
boolean stopped;

MyNewThread(String name) {
    thrd = new Thread(this, name);
    suspended = false;
    stopped = false;
    thrd.start();
}

public void run() {
    System.out.println(thrd.getName() + " starting.");
    try {
        for(int i = 0; i<1000; i++) {
            System.out.print(i + " ");
            if(i%10 == 0) {
                System.out.println();
                Thread.sleep(250);
            }

            synchronized(this) {
                while(suspended) {
                    wait();
                }
                if(stopped) break;
            }
        }
    } catch(InterruptedException ex) {
        System.out.println(thrd.getName() + " interrupted.");
    }
    System.out.println(thrd.getName() + " exiting.");
}

synchronized void mystop() {
    stopped = true;
    suspended = false;
    notify();
}

synchronized void mysuspend() {
    suspended = true;
}

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

public class Suspend {
public static void main(String[] args) {
    MyNewThread ob1 = new MyNewThread("My Thread");     
    try {
        Thread.sleep(1000);

        ob1.mysuspend();
        System.out.println("Suspending Thread.");
        Thread.sleep(1000);

        ob1.myresume();
        System.out.println("Resuming Thread.");
        Thread.sleep(1000);

        ob1.mysuspend();
        System.out.println("Suspending Thread.");
        Thread.sleep(1000);

        ob1.myresume();
        System.out.println("Resuming Thread.");
        Thread.sleep(1000);

        ob1.mysuspend();
        System.out.println("Stopping Thread.");
        ob1.mystop();
    } catch(InterruptedException ex) {
        System.out.println("Main Thread interrupted.");
    }

    try {
        ob1.thrd.join();
    } catch(InterruptedException ex) {
        System.out.println("Main Thread interrupted.");
    }
    System.out.println("Main Thread exiting.");
}
}

But this block:

synchronized(this) {
    while(suspended) {
        wait();
    }
    if(stopped) break;
}

Why this block must be specified synchronized?

I know "synchronized" uses to control Threads's access to shared resource and how to use this key word, but in the example, there're only 2 threads: Main thread and ob1 thread. And Main thread does not enter that synchronized block or any synchronized method in MyThread class. I just cant figure out the reason.

I tried to remove the "synchronized" key word precedes the block. the program returned an error in thread "My Thread" while the main thread still finished it's execution.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Tung Le Minh
  • 61
  • 1
  • 1
  • 8
  • "there're only 2 threads: Main thread and ob1 thread" Yep, that's multiple threads. "And Main thread does not enter that synchronized block" No, but it's not about entering *that* `synchronized` block, it's about entering *any* `synchronized` block which locks on the same monitor. – Andy Turner May 06 '17 at 05:09
  • "Main thread does not enter that synchronized block or any synchronized method in MyThread class" read again pls – Tung Le Minh May 06 '17 at 05:16
  • What do you think the `synchronized` keyword means on a method? – Andy Turner May 06 '17 at 05:30
  • I'm learning about Thread, I know once a synchronized method has been called on an object, the object is locked and no synchronized methods on the same object's class can be used by another thread – Tung Le Minh May 06 '17 at 05:42
  • That's not what it means exactly. Adding `synchronized` to an instance method is exactly equivalent to wrapping the entire method body in `synchronized (this) { /* body */ }`. So it creates mutual exclusion with all other blocks synchronized on `this`, not just synchronized methods. – Andy Turner May 06 '17 at 05:46
  • yeah, I see. But I still don't know why that block must be specified `synchronized`. As I see, main thread doesn't access any of those synchronized codes. And when I removed `synchronized` keyword, it return error in thread "My Thread" while running, but main thread still finished it's execution. I also tried to removed 1 or 2 `Thread. sleep(250);` along with `synchronized` to find the connection and it worked somehow without error. Can you tell me why? I've been thinking about it since yesterday. – Tung Le Minh May 06 '17 at 06:10
  • You have to call `wait()` in a `synchronized` block because that's what the specification says. You can't release a lock you don't own, and syntactically the only way you can reacquire it is if you already held it per the `synchronized` keyword in the first place. – user207421 May 06 '17 at 06:53
  • oh, shit! It's basic and i had so much thought on it. The while loop must call `wait()` as it's purpose and `wait()` only be used within `synchronized` codes. Thanks EJP! – Tung Le Minh May 06 '17 at 07:11

1 Answers1

2

To answer your direct question: you need to synchronize on this because you are calling wait() on this.

And in order for wait() to be called, the calling thread must own the monitor of the object wait() is called on.

So: you need that synchronized block (or method) to prevent an IllegalMonitorStateException for the following call to wait()!

Community
  • 1
  • 1
GhostCat
  • 137,827
  • 25
  • 176
  • 248