cutus_low
cutus_low

Reputation: 75

How to distinguish threads that have locked to different instances?

I learned that threads can lock onto "the resources", let's say an object, they're using so that only one at a time is allowed to use and modify it which is the problem of synchronization. I created two different instances of one class and fed it to my threads, trying to make sure they're locking on different "resources". How ever they still behave as though they've locked on same resources? I'm confused as I haven't had any experience and knowledge regarding threads.

So this is a code I modified from an online tutorial to try what I was thinking about:

    public class TestThread {
        public static void main(String args[]) {
        PrintDemo PD1 = new PrintDemo("No.1"); //just prints from 1 to 5
        PrintDemo PD2 = new PrintDemo("No.2");

        ThreadDemo T1 = new ThreadDemo( "Thread - 1 ", PD1 );
        ThreadDemo T2 = new ThreadDemo( "Thread - 2 ", PD2 );

        T1.start();
        T2.start();
        // wait for threads to end
        try {
            T1.join();
            T2.join();
        } catch ( Exception e) {
            System.out.println("Interrupted");
        }
    }
}

class ThreadDemo extends Thread {
    private Thread t;
    private String threadName;
    PrintDemo  PD;

    ThreadDemo( String name,  PrintDemo pd) {
        threadName = name;
        PD = pd;
    }

    public void run() {
        synchronized(PD) {
            PD.printCount();
        }
        System.out.println("Thread " +  threadName + " exiting.");
    }

    public void start () {
        System.out.println("Starting " +  threadName );
        if (t == null) {
            t = new Thread (this, threadName);
            t.start ();
        }
    }
}

class PrintDemo {
    private String name;
    PrintDemo(String name) {
        this.name = name;
    }
    public void printCount() {
        try {
            for(int i = 5; i > 0; i--) {
            System.out.println(name + " Counter   ---   "  + i );
            }
        } catch (Exception e) {
        System.out.println("Thread  interrupted.");
        }
    }
}

It should be different each time I run, but it always the same:

output:

Starting Thread - 1 
Starting Thread - 2 
No.1 Counter   ---   5
No.1 Counter   ---   4
No.1 Counter   ---   3
No.1 Counter   ---   2
No.1 Counter   ---   1
Thread Thread - 1  exiting.
No.2 Counter   ---   5
No.2 Counter   ---   4
No.2 Counter   ---   3
No.2 Counter   ---   2
No.2 Counter   ---   1
Thread Thread - 2  exiting.

edit #1: I put the entire code as you asked. i also tested the code without overriding start. it had the same result.

Upvotes: 0

Views: 46

Answers (2)

Solomon Slow
Solomon Slow

Reputation: 27115

The problem is in your ThreadDemo.start() method.

Your ThreadDemo class is declared with extends Thread, but you never actually use it as a thread. Instead, the real thread objects are created inside ThreadDemo.start().

        t = new Thread (this, threadName);
        t.start ();

Here's what probably is happening:

  1. Main thread calls T1.start(). It creates a new thread, which takes some time, and then it starts the thread.

  2. The new thread starts printing its five lines, while the main thread simultaneously calls T2.start().

  3. The T2.start() call creates another new thread, which takes some time. Meanwhile, the other thread still is printing. It doesn't print very many lines, and system.out is buffered, so chances are, it is able to print all of them before any actual I/O happens. Meanwhile...

  4. ...The main thread still is creating that T2 thread. It takes some time.

  5. Finally, the main thread is able to start the T2 thread, which prints its five lines, and...

...end of story. That's how it probably goes down.

Upvotes: 0

CWilliams
CWilliams

Reputation: 213

If you add a

Thread.sleep(1000)

between each tick of your PrintDemo, you will likely see that both threads do 5, then 4, then 3, etc. Right now the first thread is being too fast, it completes faster than the 2nd thread can be started by the main thread.

Synchronization has no effect here, both threads synchronize on different resources, which has no effect. After proving (with the Thread.sleep) that both threads execute at the same time, then add synchronization on a shared object, and both threads will fully execute one after the other, even with the waiting.

Upvotes: 1

Related Questions