Is it reasonable to synchronize on a local variable?
Asked Answered
H

4

40

From the Java memory model, we know that every thread has its own thread stack, and that local variables are placed in each thread's own thread stack.

And that other threads can't access these local variables.

So in which case should we synchronize on local variables?

Hostility answered 31/3, 2017 at 7:30 Comment(2)
Synchronization is on objects, not variables. The question doesn't make sense.Egon
@Egon Good point; I decided to reword my answer based on your input ;-)Gae
U
70

You are talking about the below case:

public class MyClass {
    public void myMethod() {
        //Assume Customer is a Class
        Customer customer = getMyCustomer();
        synchronized(customer) {
            //only one thread at a time can access customer object
              which ever holds the lock
        }
    }
}

In the above code, customer is a local reference variable, but you are still using a synchronized block to restrict access to the object customer is pointing to (by a single thread at a time).

In Java memory model, objects live in heap (even though references are local to a Thread which live in a stack) and synchronization is all about restricting access to an object on the heap by exactly one thread at a time.

In short, when you say local variable (non-primitive), only reference is local, but not the actual object itself i.e., it is actually referring to an object on the heap which can be accessed by many other threads. Because of this, you need synchronization on the object so that single thread can only access that object at a time.

Upanishad answered 31/3, 2017 at 7:41 Comment(3)
I am not very clear of this explanation. Say, call to getMyCustomer() creates and return new Customer() every time. Now the reference 'customer' will point to different objects in memory, while every thread invoking the method myMethod(). Are we making the code inside synchronized block thread safe in this case?Southerner
@SubrataNath getter methods conventionally do not create new objects to return.Jailhouse
you will see warnings in some IDEs saying that synchronisation on local variable is problematic, but that's not because it's wrong per se, but because it can easily be messed upTreasonous
P
21

There are two situations:

  1. The local variable is of a primitive type like int or double.
  2. The local variable is of a reference type like ArrayList.

In the first situation, you can't synchronize, as you can only synchronize on Objects (which are pointed to by reference-type variables).

In the second situation, it all depends on what the local variable points to. If it points to an object that other threads (can) also point to, then you need to make sure that your code is properly synchronized.

Examples: you assigned the local variable from a static or instance field, or you got the object from a shared collection.

If, however, the object was created in your thread and only assigned to that local variable, and you never give out a reference to it from your thread to another thread, and the objects implementation itself also doesn't give out references, then you don't need to worry about synchronization.

Petersburg answered 31/3, 2017 at 7:40 Comment(0)
G
6

The point is: synchronization is done for a purpose. You use it to ensure that exactly one thread can do some special protection-worthy activity at any given time.

Thus: if you need synchronization, it is always about more than one thread. And of course, then you need to lock on something that all those threads have access to.

Or in other words: there is no point in you locking the door in order to prevent yourself from entering the building.

But, as the other answer points out: it actually depends on the definition of "local" variable. Lets say you have:

void foo() {
  final Object lock = new Object();
  Thread a = new Thread() { uses lock
  Thread b = new Thread() { uses lock

then sure, that "local" variable can be used as lock for those two threads. And beyond that: that example works because synchronization happens on the monitor of a specific object. And objects reside on the heap. All of them.

Gae answered 31/3, 2017 at 7:35 Comment(0)
K
3

Yes, it does make sense when the local variable is used to synchronize access to a block of code from threads that are defined and created in the same method as the local variable.

Kindling answered 31/3, 2017 at 7:38 Comment(2)
I'd avoid this just because of bug-proneness and clarity issues. Well, I'd avoid synchronized in this day and age anyway.Outride
Absolutely @Outride . Only the question was not about effectiveness of such a code, but possibility to have such a construct doing a meaningful job. I could imagine code generators spitting out such source code.Otto

© 2022 - 2024 — McMap. All rights reserved.