views:

135

answers:

4

Hi all,

do i need to synchronize this, when many threads accessing the get Method and only one thread is accessing the setList method?

public class ListContainer {
  private List<String> myList = new ArrayList<String();

  public List<String> get ( )
  {
    return new ArrayList<String>(myList);
  }

  public List<String> set ( )
  {
    this.myList = computeList();
  }
}

I dont care if readers get old data, but the data should be consistent.

Janning

+4  A: 

You don't have to synchronize (but you must declare myList as volatile) if the following conditions are true:

  • computeList doesn't depend on the current state of myList
  • You don't change content of the list after it was assigned (Collections.unmodifiableList(computeList()) is the better way to express this condition)
axtavt
+1 for unmodifiableList
Poindexter
great thanks to both! second answer was slighty better :-)
Janning
+1  A: 

No, you don't need there synchronization. There are no any concurrent modifications (if computeList() doesnt depends on the myList).

btw, why are you returning new ArrayList(myList) instead of simply return myList?

splix
@splix Probably because he doesn't want his list get modified by a client outside the class. Returning `myList` would expose a reference to the list, thus the client would be able to change it any way he wants. And _that_ would be a classic concurrency bug...
Péter Török
you are right, returning the list must be thread-safe, too.
Janning
A: 

It does not matter whether computeList depends on myList or not, as long as there is only reading access to the content of myList no synchronisation problem can arise.

If not using volatile for myList then it might occur that get returns the old myList, even though strictly set has already replaced the list. If you don't mind this situation (it could lead to two threads seeing different values), then you don't need volatile.

Christopher Oezbek
A: 

I would rather do the copy implicit by

public class ListContainer {

    private final List<String> myList = new CopyOnWriteArrayList<String>();

    public List<String> get (){
      return myList;
    }

    public List<String> set (){
       computeList();
    }
}

HTH

anonymous