0

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.

cutus_low
  • 85
  • 5
  • How often have you run the code? Having the same output twice is quite possible, 2000 times is still possible but more unlikely. Maybe don't print 5 times but 1000 times to give the threads more time to diverge. – luk2302 Aug 14 '19 at 18:57
  • 2
    Why did you override the `start()` method? What's the `...` hiding there? Overriding `start()` is very unusual. – Solomon Slow Aug 14 '19 at 19:01
  • 4
    Do not extend `Thread`, instead implement `Runnable`. You might have caused a problem by overriding `Thread.start()` which prevents `Thread` from actually running in a separate thread. Don't do this. – Karol Dowbecki Aug 14 '19 at 19:04
  • P.S., It's not true that the interleaving of lines printed by the two threads _should_ be different every time. It merely is the case that it _could_ be different. I know it's somewhat suspicious that the first thread always runs to completion before the second even begins, but that's all it is--suspicious--it doesn't prove that there's anything wrong with your Java runtime or your OS. – Solomon Slow Aug 14 '19 at 19:18
  • @SolomonSlow I edited the post so you can see what it is. I also tried it without overriding start. same result – cutus_low Aug 14 '19 at 20:16

2 Answers2

1

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.

CWilliams
  • 213
  • 1
  • 7
0

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.

Solomon Slow
  • 25,130
  • 5
  • 37
  • 57