Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronizing access to Immutable Integer object

Code snippet - 1

class RequestObject implements Runnable
{
    private static Integer nRequests = 0;

    @Override
    public void run()
    {       
        synchronized (nRequests)
        {
            nRequests++;
        }
    }
}

Code snippet - 2

class RequestObject implements Runnable
{
    private static Integer nRequests = 0;
    private static Object lock = new Object();

    @Override
    public void run()
    {       
        synchronized (lock)
        {
            nRequests++;
        }
    }
}

While the second code snippet is working fine without causing any race conditions, the first one isn't successful in synchronizing access to the static data member between different instances of the same class(RequestObject). Could somebody throw more light on this. I would like to understand why the first approach isn't working.

My original implementation is the first one. The later I saw in https://stackoverflow.com/a/2120409/134387.

like image 816
Abhijith Madhav Avatar asked Aug 03 '13 07:08

Abhijith Madhav


People also ask

Are immutable object synchronized?

An immutable object is one whose state cannot be changed once it is created. Since there is no method that can change the state of any of the object's instance variables once the object is created, there is no need to synchronize on any of the object's methods.

Does immutable classes require synchronization?

Immutable objects are inherently thread-safe. They do not require synchronization.

Can we use synchronize for variables in Java?

You can have both static synchronized method and nonstatic synchronized method and synchronized blocks in Java but we can not have synchronized variable in java. Using synchronized keyword with a variable is illegal and will result in compilation error.

Can we use synchronized keyword with variable?

Synchronized is the modifier applicable only for methods and blocks but not for the variables and for classes. There may be a chance of data inconsistency problem to overcome this problem we should go for a synchronized keyword when multiple threads are trying to operate simultaneously on the same java object.


2 Answers

You are constantly creating new Integer objects, which you then synchronize on, which at least makes it extremely confusing to think about it. So you can get the following scenario:

Thread A gets hold of the current value of nRequests (lets say 0)

Thread B queues for the same value (0)

Thread A increases nRequests (to the value 1)

Thread C gets hold of the new value and synchronizes on it, increases it and lets go of the value.

Thread A lets go of the monitor on 0

Thread B synchronizes on 0 and increases it to 1, overwriting the changes of C

With the second approach you have a single object that everybody has to synchronize on. Which is exactly what you want.

like image 149
Jens Schauder Avatar answered Nov 04 '22 00:11

Jens Schauder


Instances of Integer are immutable, nRequests++ therefore creates a new Integer object to hold the result, and stores it in nRequests. The synchronized statement synchronizes on an object. Therefore, the threads will synchronize on different objects. Yes, there may be only one thread in a synchronized block on the same object at the same time, but different threads may be in synchronized blocks of different objects at the same time ...

The easiest way to synchronize access to static state is putting it in a static synchronized method:

static synchronized void increment() {
    nRequests++;
}

This is equivalent to the following synchronized block:

synchronized (RequestObject.class) {
    nRequests++;
}

where RequestObject is the class containing the static field.

like image 45
meriton Avatar answered Nov 04 '22 01:11

meriton