Sincronização de threads

Defini uma thread Calculator que calcula uma somatória e disponibiliza o resultado através do método getTotal(). A thread Reader mantém uma referência a Calculator e envia para a saída padrão o resultado calculado.
Como minha intenção era de que o print só fosse feito após o cálculo, Reader invoca wait() antes de invocar getTotal(). Já Calculator chama notify() após o cálculo.
No método main, crio uma instância de Calculator e três instâncias de Reader. Segue abaixo o código:

public class Calculator extends Thread {

    private int total;
    
    public void run() {
        for (int i = 0; i < 10; i++)
            total += i;
        try {
            Thread.sleep(1000);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }

        synchronized (this) {
            notify();
        }
    }
    public int getTotal() {
        return total;
    }
}
public class Reader extends Thread {
    Calculator c;

    public Reader(Calculator c) {
        this.c = c;
    }

    public void run() {
        synchronized (c) {
            try {
                String name = Thread.currentThread().getName();
                System.out.println(name + " is waiting...");
                c.wait();
                System.out.println("(" + Thread.currentThread().getName() + ") total is: " + c.getTotal());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }

    public static void main(String[] args) {
        Calculator c = new Calculator();
        new Reader(c).start();
        new Reader(c).start();
        new Reader(c).start();
        c.start();
    }
}

Agora a parte curiosa: como notify() só é invocado uma vez, no máximo uma instância de Reader seria desbloqueda. Entretanto, a saída apresentada pelo programa foi a seguinte:

Thread-1 is waiting…
Thread-2 is waiting…
Thread-3 is waiting…
(Thread-1) total is: 45
(Thread-2) total is: 45
(Thread-3) total is: 45

Mesmo comentando a linha onde notify() é invocado, a saída é a mesma.
Sem entender o que aconteceu, modifiquei a forma como a thread Calculator era iniciada, trocando c.start(); por new Thread©.start();. Com isso, a saída foi a que eu esperava de início:

Thread-1 is waiting…
Thread-2 is waiting…
Thread-3 is waiting…
(Thread-1) total is: 45

Como isso é possível ? Imaginava que o mecanismo de sincronização era independente da forma de criação das threads.

Grato

é muito esquisito… vou ficar por aqui esperando alguem desvendar esse mistério…