Search code examples
javamultithreadingsynchronizationthread-safetythread-sleep

Java synchronization(object locking) not working as expected


Please consider the below code.

import static java.lang.System.out;

public class Task
{
    public Integer k =  new Integer(10) ;

    public Task()
    {
        out.println(k + " constructor of Task : " + Thread.currentThread().getName());
    }
}

import static java.lang.System.out;

public class Executor2 implements Runnable
{
    private Task task;
    public Executor2(Task t)
    {
        out.println("constructor of Executor2 : " + Thread.currentThread().getName());
        task = t;
    }

    @Override
    public void run()
    {
        synchronized(task.k)
        {
            task.k = 88;
            out.println("changed value of task.k to : " + task.k + " " + Thread.currentThread().getName());
            try
            {
                out.println("sleeping");
                Thread.sleep(5000);
            }
            catch (InterruptedException ex)
            {
                ex.printStackTrace(out);
            }
            out.println("done");
        }
    }
}

import static java.lang.System.out;

public class Executor3 implements Runnable
{
    private Task task;
    public Executor3(Task t)
    {
        out.println("constructor of Executor3 : " + Thread.currentThread().getName());
        task = t;
    }

    @Override
    public void run()
    {
        synchronized(task.k)
        {
          task.k = 888;
          out.println("changed value of task.k to : " + task.k + " " + Thread.currentThread().getName());
        }
    }
}
------------------------------------------------------------
public class Main
{
    public static void main(String[] args)
    {
        Task task = new Task();

        Executor2 executor2 = new Executor2(task);
        Thread thread2 = new Thread(executor2);
        thread2.start();

        Executor3 executor3 = new Executor3(task);
        Thread thread3 = new Thread(executor3);
        thread3.start();
    }
}

Below is the output of the program.

10 constructor of Task : main
constructor of Executor2 : main
constructor of Executor3 : main
changed value of task.k to : 88 Thread-0
sleeping
changed value of task.k to : 888 Thread-1
done

The surprising thing here is output line : changed value of task.k to : 888 Thread-1 which is not expected to be printed before output line : done. How come the lock on Integer object is released before sleep duration has passed?

Thanks.


Solution

  •     synchronized(task.k)
        {
          task.k = 888;
    

    Changing the object you're synchronizing on kind of defeats the point of the synchronization. You then try to print the new object while you're still synchronized on the old one. Don't replace objects threads are synchronizing on!