1

Following code gives a fixed output as 400000000 whereas when I am removing static keyword from synchronized addOne method I am getting random output any integer less that 400000000.
Can anyone please explain that ?

public class ThreadTest extends Thread{

public static int sharedVar = 0;

private static synchronized void addOne()
{
    for (int i = 0; i < 200000000; i++)
    {
        sharedVar++;
    }
}

@Override
public void run()
{
    addOne();
}

public static void main(String[] args)
{
    ThreadTest mt1 = new ThreadTest();
    ThreadTest mt2 = new ThreadTest();
    try
    {
        // wait for the threads
        mt1.start();
        mt2.start();    
        mt1.join();
        mt2.join();
        System.out.println(sharedVar);
    }
    catch (InterruptedException e1)
    {
        e1.printStackTrace();
    }
}
}
  • See http://stackoverflow.com/questions/1149928/what-is-the-difference-between-a-synchronized-method-and-synchronized-block-in-j – mjn Jun 14 '16 at 18:30
  • See http://stackoverflow.com/questions/2120248/how-to-synchronize-a-static-variable-among-threads-running-different-instances-o – mjn Jun 14 '16 at 18:31

2 Answers2

0

Change your addOne() method slightly, as shown below to understand the behavior.

private static synchronized void addOne() {
    for (int i = 0; i < 5; i++) {
        sharedVar++;
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
        }
        System.out.println(Thread.currentThread().getName());
    }
}

with static the output is:

Thread-0
Thread-0
Thread-0
Thread-0
Thread-0
Thread-1
Thread-1
Thread-1
Thread-1
Thread-1

without static the output is:

Thread-0
Thread-1
Thread-0
Thread-1
Thread-0
Thread-1
Thread-1
Thread-0
Thread-0
Thread-1

If you need more info to understand it, then please refer oracle thread synchronization tutorial.

K139
  • 3,654
  • 13
  • 17
0

When a method is static, it essentially belongs to the class definition; so when multiple instances of the class call the method, they're all pointing towards that one static representation. When it's not static, it's useful to think of the method belonging to all of the individual instances of that class.

In terms of your application, when the method isn't static, you synchronize along an instance's method only, and not a 'shared' method. When it comes to running your Threads, they both find that they immediately have access to both of their respective methods as you only achieve synchronization on the runtime instance. In this respect, if you wanted to call addOne() from different Threads on the same instance, that would prevent race conditions. However in your application you're trying to synchronize along a global variable, not the members of a runtime instance, so the method should either remain static or your shared data should be moved to a shared object that may be synchronized upon.

Mapsy
  • 4,192
  • 1
  • 37
  • 43