What is the difference between Thread.join and Synchronized?

20.3k Views Asked by At

I am confused when to use Thread.join() and when to use synchronization in multi threading application.

According to me, both of them block or wait for the execution to be done by some other thread.
This example has to output 10 A's , 10 B's & 10 C's in sequential pattern one after other like :

1  : A
2  : A
3  : A
4  : A
5  : A
6  : A
7  : A
8  : A
9  : A
10 : A
1  : B
2  : B
3  : B
4  : B
5  : B
6  : B
7  : B
8  : B
9  : B
10 : B
1  : C
2  : C
3  : C
4  : C
5  : C
6  : C
7  : C
8  : C
9  : C
10 : C
----ProGraM ENDS----

Example starts here

class SyncTest extends Thread 
{   
    StringBuffer sb;

    public SyncTest(StringBuffer sb) 
    {
        this.sb = sb;   
    }

    public void run()
    {
        synchronized(sb) 
        {
            for(int i=1;i<=10;i++){
                System.out.println(i+" : "+sb.charAt(0));
            }
            sb.setCharAt(0, (char) (sb.charAt(0)+1));
        }
    }

    public static void main(String [] args) throws InterruptedException
    {
        StringBuffer sb = new StringBuffer("A");
        Thread t1=new SyncTest(sb);
        Thread t2=new SyncTest(sb);
        Thread t3=new SyncTest(sb);

        t1.start();

        t2.start();

        t3.start();

        Thread.sleep(1000);

        System.out.println("----ProGraM ENDS----");
    }
}

Here, output turns out to be 10 A's followed by 10 B's followed by 10 C's in a sequential order. But I can also use Thread.join instead of synchronized block to get the same output like this:

public void run()
    {
        //removed synchronized statement...

            for(int i=1;i<=10;i++){
                System.out.println(i+" : "+sb.charAt(0));
            }
            sb.setCharAt(0, (char) (sb.charAt(0)+1));

    }

    public static void main(String [] args) throws InterruptedException
    {
        StringBuffer sb = new StringBuffer("A");
        Thread t1=new SyncTest(sb);
        Thread t2=new SyncTest(sb);
        Thread t3=new SyncTest(sb);

        t1.start();
        t1.join();
        t2.start(); // wait for t1 to complete
        t2.join();
        t3.start(); // wait for t2 to complete
        t3.join(); 

                     // wait for t3 to complete
        System.out.println("----ProGraM ENDS----");
    }

Can anyone clear my confusion on usage of these 2 techniques i.e. when to use Thread.join and when to use synchronization in Multi-threading on Java.

6

There are 6 best solutions below

5
On BEST ANSWER

Thread.join() waits for the thread to completely finish, whereas a synchronized block can be used to prevent two threads from executing the same piece of code at the same time.

It's hard to advise when to use one over the other in general, since they serve different purposes. It's rare to find an example, such as your code, where the difference between the two is minimal.

That being said, in your first example there is no guarantee the output will be alphabetical. You can't be sure which thread will get to the synchronized block first. So in this particular case, join() is most appropriate.

1
On

The synchronized keyword enables a locking mechanism that allows threads to not step on each other. Java documentation describes this as a way to " preventing thread interference and memory consistency errors".

If you use join(), it makes sure that as soon as a thread calls join,the current thread(running thread) will not execute unless the thread you have called join is finished. I think the diagram below might help visualize this better.

enter image description here

Source

0
On

thread.join() stops the execution of current thread until the joined thread completes.. You have commented correctly.. :)

Synchronization prevents multiple threads from executing the synchronized part of code on the same instance.

0
On

Without join() thread runs in parallel and depend upon OS time slice (which to start first). With join() thread runs in series. For eg: Suppose you have two threads with both calling join() method

MyThread t1 = new MyThread();
MyThread t2 = new MyThread();

t1.join(); // this will be start first.
t2.join(); // this will be start only after above.

Now without join() method, any of t1 and t2 can start first. There's is no guarantee.

synchronized statement/keyword is used for monitoring the thread, so that only one thread can access that synchronized method/variable at a time. It doesn't matter if you use join() or not.

If you use synchronized with join(), you have a guarantee that thread t1 can only access first. Without synchronized both t1 and t2 thread can access at any time but these threads start and die. in series because of join().

0
On

They are obviously NOT the same but, if they are going to be used for the same purpose (serializing access/execution ) then synchronized blocks can be thought as a more flexible version than using joins since it's usage is agnostic about particular thread instances on which you want to serialize execution.

Moreover, in synchronized blocks the shared data block concept is more emphasized than joins.

0
On

Simple example :

You have a static string table where some threads will be putting some values . The table is initialized with "empty" . the table is accessed with a static index. If a thread puts a value, it will increment the static index .

If you synchronize the threads it will make sure that any value put by a thread can not be overriden by another thread .

if you use join on threads, only the first joinded thread will have the opportunity to put the values in the table .As the other will be waiting but knowing that the index is incremented they wont be able to access the table (null pointer exception) . So Join has made the other thread useless.

This example uses threads on same instance containing the synchronized method.