views:

216

answers:

6

Hi,

I like to know do we synchronize the instance variable which are final. As variables are final there can not be change in the value. Can anybody explain this?

+3  A: 

An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed

Taken from Synchronized Methods

Anthony Forloney
A: 

There is no need to synchronize access to final instance variables.

see http://java.sun.com/docs/books/tutorial/essential/concurrency/syncmeth.html

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed) This strategy is effective, but can present problems with liveness, as we'll see later in this lesson.

john
A: 

You typically would not mark accessor methods as synchronized if the method was returning the value of a final variable; e.g.

private final String message = "Hello, World";

// No need to mark as synchronized as message can never change.
public String getMessage() {
  return message;
}

However, you may wish to synchronize on the final variable, for example if you were using it as a lock; e.g.

private final Object lock;

...

synchronized(lock) {
  // Do something in critical section.
}
Adamski
+1  A: 

Well yes. When you declare a final instance variable with a reference type, the reference is immutable but the object it refers to typically is mutable. If there may be multiple threads accessing and updating the state of mutable object, the operations on the final instance need to be synchronized.

For example:

public class Thing {
   private final List l1 = 
   private final List l2 = 
   private final List l3 = 

   ...

   public void l1ToL2() {
       l2.add(l1.removeFirst());
   }

   public void l2ToL3() {
       l3.add(l2.removeFirst());
   }
}

If we don't do something to synchronize those methods' use of l1, l2 and l3, they are not thread-safe, and concurrent operations from different threads could corrupt the lists.

On the other hand, this is thread-safe, for the reasons stated in @Anthony Forloney's answer.

public class Thing {
   private final int i = ... ;

   public int getI() {
       return i;
   }
}
Stephen C
+3  A: 

Do we synchronize instance variables which are final?

Yes. You still have to synchronize mutable objects

final != immutable

 public class Something {
     private final List list = new ArrayList();

     public void add( String value ) {
         this.list.add( value );
     }
     public int count() {
          return this.list.size();
     }
 }

Later

 Something s = new Something();

 Thread a = new Thread() {
    public void run(){
       s.add( "s" );
       s.add( "s" );
       s.add( "s" );
     }
 };
 Thread b = new Thread(){
     public void run() {
         s.count();
         s.count();
     }
 };

 a.start();
 b.start();

If yes then whats the use?

You're declaring, that a given attribute can't be changed during the object life time.

This increases the security ( your object attribute can't be replaced by a malicious subclass ) Allows compiler optimizations ( because it knows that only a reference will be used ever ) Prevents subclasses from changing it and so on.

An attribute that is both, final and immutable ( like String, Integer and others ) doesn't need synchronization.

class X {
    private final String name = "Oscar";

    public int nameCount(){
        return this.name.length(); //<-- Will return 5 ALWAYS ( actually the compiler might inline it 
    }
 }
OscarRyz
+1  A: 

If the instance variable isn't immutable, then the state of that variable can still be changed even if it is final. Take, for example:

private final List<Foo> foos = new ArrayList<Foo>();


public void addFoo(Foo newFoo){
      foos.add(newFoo);
}

public Foo popFoo(){
     return foos.remove(0);
}

In this situation, even though foos is final, a Foo can be added by Thread B while Thread A is attempting to remove an element, leading to potentially iconsistent state.

The Sychronized Methods tutorial mentioned in other examples is correct in that reading a final variable does not need to be sychronized. However, if the variable is mutable(as List<T> is), then writing to that variable must be synchronized to guarantee a "happens-before" relationship. If, however, the variable is immutable, then of course writes are not allowed to that variable anyway, so there is no need to synchronize.

Scott Fines