-2

I was practicing multithreading in java and wrote the below code

class Printer {
    synchronized void printHi(String x) {
        System.out.println(x);
    }
}

class MyThread extends Thread {
    Printer objm;

    MyThread(Printer a) {
        objm = a;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            objm.printHi("MyThread" + i);
        }
    }
}

class YourThread extends Thread {
    Printer objy;

    YourThread(Printer a) {
        objy = a;
    }

    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            objy.printHi("YourThread" + i);
        }
    }
}

public class test {
    public static void main(String[] args) {
        Printer ob = new Printer();
        MyThread mt = new MyThread(ob);
        YourThread yt = new YourThread(ob);
        mt.start();
        yt.start();
    }
}

Sometimes I gets the output as:

MyThread0
YourThread0
MyThread1
YourThread1
MyThread2
YourThread2
MyThread3
YourThread3
YourThread4
MyThread4
MyThread5
MyThread6
YourThread5 
MyThread7
YourThread6
MyThread8
MyThread9
YourThread7
YourThread8
YourThread9

Which is asynchronous. Why is it so even after making the function printHi() as synchronized?

rkosegi
  • 14,165
  • 5
  • 50
  • 83
Hari Krishnan
  • 5,992
  • 9
  • 37
  • 55

2 Answers2

3

Synchronized means only one thread can be running a block of code marked synchronized on the same lock object (instance of the object for the case of a synchronized method). It does not mean threads will run in order. It is perfectly correct for the two threads to enter those synchronized blocks in any order, and any number of times before the next thread does. What you want is much more difficult and beyond what a simple synchronized block can do.

If you want it to always go Thread A, Thread B, Thread A, Thread B- first I'd question that those two things should actually be separate threads. Wanting things to run sequentially like that is the number one sign you aren't asynchronous and shouldn't be multiple threads. But if they do, you're probably best off with two threads with message handlers, sending messages to each other about when they're allowed to run. Or using semaphores to signal each other. It's hard to give exact advice because the problem here is obviously a trivialized version of something harder, and without the details the right implementation is hard to guess.

Gabe Sechan
  • 90,003
  • 9
  • 87
  • 127
1

You're synchronizing the printHi function call. That means two instances of printHi on the same object won't run at the same time. That's great. It means you'll never get output like

MyThYourThreadread77

(Side note: Java's printing primitives are already somewhat synchronized if I recall correctly, so that shouldn't happen anyway. But for demonstrative purposes, it'll do)

However, your loop is not synchronized. If you want the whole loop to only happen in one thread at a time, remove synchronized from print and write your loop as

synchronized (objm) {
    for (int i = 0; i < 10; i++) {
        objm.printHi("MyThread" + i);
    }
}

(and the same for objy in YourThread)

There's still no guarantee on which one will happen first, but the two loops won't interrupt each other in this case.

Silvio Mayolo
  • 62,821
  • 6
  • 74
  • 116