javamultithreadingconcurrencymonitors

Different threads synchronizing on different objects


Please look at this code

public class Test extends Thread {
    int i;
    public Test(int i) {this.i = i;}

    void simpleBlock() throws InterruptedException {
        System.out.println(i + " this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.");
        synchronized(this) {wait();}
    }

    public void run() {
        try {simpleBlock();} catch (InterruptedException e) {}
    }
}

This is implemented by a Main class that creates and starts the threads

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Test[] t = new Test[20];
        for (int i=0; i<20; i++) {
            t[i] = new Test(i);
            t[i].start();
        }
    }
}

this prints the following output

0 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
6 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
4 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
3 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
5 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
2 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
1 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
14 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
7 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
13 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
12 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
10 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
11 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
9 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
8 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
18 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
19 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
17 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
16 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.
15 this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.

Since SimpleBlock() is not synchronized, I was expecting the prints to be chopped randomly. At least, that's what happened with another synchronization test I ran a while back, except that time I was using Semaphores (or lack thereof).

So why does each Thread print the full string in such a nice orderly fashion?

And this leads me to my next inquiry.

Let's say that simpleBlock is fully synchronized, and the output is the same as above. So,

    synchronized void simpleBlock() throws InterruptedException {
        System.out.println(i + " this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.");
        wait();
    }

As you may already know, this is equivalent to

    void simpleBlock() throws InterruptedException {
        synchronized(this) {
            System.out.println(i + " this is an example of a thread blocking on itself - practicing concurrency 101, monitors, etc.");
            this.wait();
        }
    }

Am I correct in assuming that since 20 threads are created in the Main class above, no two threads synchronize on a shared object since each thread is its own unique object, and because of this, synchronization schemes will effectively fail?

In other words, is it a bad idea to create many threads, each synchronizing on itself?


Solution

  • PrintStream.println is synchronized so your output is relatively orderly even if you have lots of threads.

    From the source

    /**
     * Prints a String and then terminate the line.  This method behaves as
     * though it invokes <code>{@link #print(String)}</code> and then
     * <code>{@link #println()}</code>.
     *
     * @param x  The <code>String</code> to be printed.
     */
    public void println(String x) {
        synchronized (this) {
            print(x);
            newLine();
        }
    }