0

i have a simple code piece bellow:

public class ThreadA {
public static void main(String[] args){
    ThreadB b = new ThreadB();
    b.start();

    synchronized(b){
        try{
            System.out.println("Waiting for b to complete...");
            b.wait();
        }catch(InterruptedException e){
            e.printStackTrace();
        }

        System.out.println("Total is: " + b.total);
    }
}



class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();
        }
    }
}

Result:

Waiting for b to complete...
Total is: 4950

and i have a problem why we need use this code, i am not clearly here.

 synchronized(this){
        for(int i=0; i<100 ; i++){
            total += i;
        }
        notify();
    }

when i dont use synchronized here, i have the same result.

Lão Tà
  • 78
  • 1
  • 9

2 Answers2

1

When notify() is called and corresponding wait() sees that, a "happens-before" relationship is established: everything that happened in ThreadB prior to notify() will be visible in ThreadA after corresponding wait() returns. So, in your case all modifications to total are completed before notify() and it's safe to assume that ThreadA will see these changes.

However, note that it's incorrect way to use wait()/notify() for synchronization. There can be spurious wakeups (i.e. wait() waking up without corresponding notify()). There are specific idiomatic ways to use these methods (they're actually POSIX conditional variables in disguise). One of them is to define a "condition" which can be checked from both threads (e.g. "is_completed variable is true) and call wait() in a loop, see here

yeputons
  • 8,478
  • 34
  • 67
0

When a thread terminates it calls this.notifyAll(), so your call to notify() in ThreadB isn't strictly necessary.

However, as the documentation for Thread.join() notes, the use of monitor operations on Thread objects is not recommended:

As a thread terminates the this.notifyAllmethod is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.

If you want to wait for ThreadB to complete, just call b.join() from ThreadA. You don't need any synchronized blocks:

public class ThreadA {
    public static void main(String[] args) throws InterruptedException {
        ThreadB b = new ThreadB();
        b.start();
        System.out.println("Waiting for b to complete...");
        b.join();
        System.out.println("Total is: " + b.total);
    }
}

public class ThreadB extends Thread {
    int total;

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            total += i;
        }
    }
}
teppic
  • 7,051
  • 1
  • 29
  • 35