Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java concurrent Array List access

I have an object which is a singleton. This object declares:

List<Player> players = new ArrayList<Player>();

The same object also specifies 4 operations on this arrayList:

public List<Player> getPlayers() {
return players;
} // the result of this method can be used in another object as an iterator (or maybe by index-access)

and

public void removePlayer(Player player) {
players.remove(player);
}

public void addPlayer(Player player) {
players.add(player);
}

public boolean isPresent(Player player) {
if (players.constans(player)) {...
}

Right now in the constructor I am doing it like that:

players = Collections.synchronizedList(new ArrayList<Player>());

But what is the CORRECT way to synchronize these methods. It seems like if I use iterator in another class, it will still through the concurrent modification exception. Does the exception happen if a 2 threads call at the same time the "remove" and "contains" method? There are many threads to access the singleton so I would like to know the method to do this with the minimum hit on performance.

like image 981
Artem Moskalev Avatar asked Jul 10 '13 18:07

Artem Moskalev


People also ask

Is there a concurrent ArrayList?

CopyOnWriteArrayList is a thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are implemented by making a fresh copy of the underlying array. CopyOnWriteArrayList is a concurrent alternative of synchronized List implements List interface and its part of java. util.

Is Java ArrayList thread-safe?

Any method that touches the Vector 's contents is thread safe. ArrayList , on the other hand, is unsynchronized, making them, therefore, not thread safe. With that difference in mind, using synchronization will incur a performance hit. So if you don't need a thread-safe collection, use the ArrayList .

What happens if multiple threads access Linkedlist ArrayList?

Implementation of ArrayList is not synchronized by default. It means if a thread modifies it structurally and multiple threads access it concurrently, it must be synchronized externally. Structural modification implies the addition or deletion of element(s) from the list or explicitly resizes the backing array.

What is copy ArrayList writing?

CopyOnWriteArrayList is a thread-safe variant of ArrayList where operations which can change the ArrayList (add, update, set methods) creates a clone of the underlying array. CopyOnWriteArrayList is to be used in a Thread based environment where read operations are very frequent and update operations are rare.


2 Answers

The documentation answers your question.

It is imperative that the user manually synchronize on the returned list when iterating over it:

List list = Collections.synchronizedList(new ArrayList());
      ...
  synchronized(list) {
      Iterator i = list.iterator(); // Must be in synchronized block
      while (i.hasNext())
          foo(i.next());
  }

As for contains and remove, you shouldn't have to synchronize manually. I'm looking at the source code of Collections and it looks like it does that for you:

    public boolean contains(Object o) {
        synchronized (mutex) {return c.contains(o);}
    }
    public boolean remove(Object o) {
        synchronized (mutex) {return c.remove(o);}
    }

It wouldn't be a synchronized list if you have to do this stuff on your own.

like image 137
Daniel Kaplan Avatar answered Sep 30 '22 17:09

Daniel Kaplan


If you don't plan on updating it often use a CopyOnWriteArrayList otherwise @tieTYT's suggestion works.

You can also manage this yourself by returning a copy of the list instead of the actual list within the getPlayers. (If you are using Collections.synchronizedList)

public List<Player> getPlayers(){
    synchronized(list){
       Collections.unmodifiableList(new ArrayList<Player>(list));
    }
}

This has the side effect of a list being out of date after an add/remove is done

Edit: Stealing Grzegorz suggestion for unmodifiableList

like image 43
John Vint Avatar answered Sep 30 '22 18:09

John Vint