Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Synchronization of non-final field

A warning is showing every time I synchronize on a non-final class field. Here is the code:

public class X  
{  
   private Object o;  

   public void setO(Object o)  
   {  
     this.o = o;  
   }  

   public void x()  
   {  
     synchronized (o) // synchronization on a non-final field  
     {  
     }  
   }  
 } 

so I changed the coding in the following way:

 public class X  
 {  

   private final Object o;       
   public X()
   {  
     o = new Object();  
   }  

   public void x()  
   {  
     synchronized (o)
     {  
     }  
   }  
 }  

I am not sure the above code is the proper way to synchronize on a non-final class field. How can I synchronize a non final field?

like image 687
divz Avatar asked Aug 02 '11 10:08

divz


2 Answers

First of all, I encourage you to really try hard to deal with concurrency issues on a higher level of abstraction, i.e. solving it using classes from java.util.concurrent such as ExecutorServices, Callables, Futures etc.

That being said, there's nothing wrong with synchronizing on a non-final field per se. You just need to keep in mind that if the object reference changes, the same section of code may be run in parallel. I.e., if one thread runs the code in the synchronized block and someone calls setO(...), another thread can run the same synchronized block on the same instance concurrently.

Synchronize on the object which you need exclusive access to (or, better yet, an object dedicated to guarding it).

like image 149
aioobe Avatar answered Oct 09 '22 00:10

aioobe


It's really not a good idea - because your synchronized blocks are no longer really synchronized in a consistent way.

Assuming the synchronized blocks are meant to be ensuring that only one thread accesses some shared data at a time, consider:

  • Thread 1 enters the synchronized block. Yay - it has exclusive access to the shared data...
  • Thread 2 calls setO()
  • Thread 3 (or still 2...) enters the synchronized block. Eek! It think it has exclusive access to the shared data, but thread 1 is still furtling with it...

Why would you want this to happen? Maybe there are some very specialized situations where it makes sense... but you'd have to present me with a specific use case (along with ways of mitigating the sort of scenario I've given above) before I'd be happy with it.

like image 32
Jon Skeet Avatar answered Oct 08 '22 23:10

Jon Skeet