Collections.synchronizedList and synchronized - java

List<String> list = Collections.synchronizedList(new ArrayList<String>());
synchronized (list) {
list.add("message");
}
Is the block "synchronized (list){} " really need here ?

You don't need to synchronize as you put in your example. HOWEVER, very important, you need to synchronize around the list when you iterate it (as noted in the Javadoc):
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());
}

It depends on the exact contents of the synchronized block:
If the block performs a single, atomic operation on the list (as in your example), the synchronized is superfluous.
If the block performs multiple operations on the list -- and needs to maintain the lock for the duration of the compound operation -- then the synchronized is not superfluous. One common example of this is iterating over the list.

The underlying code for Collections.synchronizedList add method is:
public void add(int index, E element) {
synchronized (mutex) {list.add(index, element);}
}
So in your example it is not needed to add synchronisation.

Also Important to note that any methods that use Iterators for example Collections.sort() will also need to be encapsulated inside a synchronized block.

Read this Oracle Doc
It says "It is imperative that the user manually synchronize on the returned list when iterating over it"

Like what has been mentioned by others, the synchronized collections are thread-safe, but the compound actions to these collections are not guaranteed to be thread-safe by default.
According to JCIP, the common compound actions can be
iteration
navigation
put-if-absent
check-then-act
The OP's synchronized code block isn't a compound action, so no difference whether add it or not.
Let's take the example from JCIP and modify it a little to clarify why it's necessary to guard the compound actions with lock.
There are two methods that operate on same collection list that wrapped by Collections.synchronizedList
public Object getLast(List<String> list){
int lastIndex = list.size() - 1;
return list.get(lastIndex);
}
public void deleteLast(List<String> list){
int lastIndex = list.size() - 1;
list.remove(lastIndex);
}
If methods getLast and deleteLast are called at the same time by two different threads, below interleaves may happen and getLast will throw ArrayIndexOutOfBoundsException. Assume current lastIndex is 10.
Thread A (deleteLast) --> remove
Thread B (getLast) --------------------> get
The Thread A remove the element before the get operation in Thread B. Thus, the Thread B still use 10 as the lastIndex to call list.get method, it will lead to concurrent problem.

Related

Why do we use synchronized collection if it doesn't guarantee the synchronized access on iterators?

For example, in the code below, we have to wrap list in a synchronized block when doing the iteration. Does the Collections.synchronizedList make the list synchronized? Why do we do this if it doesn't provide any convenience? Thanks!
List<Integer> list = Collections.synchronizedList( new ArrayList<>(Arrays.asList(4,3,52)));
synchronized(list) {
for(int data: list)
System.out.print(data+" ");
}
See https://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html
The reason is that iteration is accomplished via multiple calls into the collection, which must be composed into a single atomic operation.
Also see https://www.baeldung.com/java-synchronized-collections
Why do we do this if it doesn't provide any convenience
That it does not help you when iterating is not the same as providing no convenience.
All of the methods - get, size, set, isEmpty etc - are synchronized. This means that they have visibility of all writes made in any thread.
Without the synchronization, there is no guarantee that updates made in one thread are visible to any other threads, so one thread might see a size of 5 which another sees a size of 6, for example.
The mechanism for making the list synchronized is to make all of its methods synchronized: this effectively means that the body of the method is wrapped in a synchronized (this) { ... } block.
This is still true of the iterator() method: that too is synchronized. But the synchronized block finishes when iterator() returns, not when you finish iterating. It's a fundamental limitation of the way the language is designed.
So you have to help the language by adding the synchronized block yourself.
Wrapper is used to synchronize addition and removal elements from wrapped collection.
JavaDoc mentions that iteration is not synchronized an you need to synchronize it yourself.
* It is imperative that the user manually synchronize on the returned
* list when iterating over it
But other access operations are thread-safe and also establish happens before relation (since they use synchronized).
Collections.synchronizedList method synchronises methods like add, remove. However, it does not synzhronize iterator() method. Consider the following scenario:
Thread 1 is iterating through the list
Thread 2 is adding an element into it
In this case, you will get ConcurrentModificationException and hence, it's imperative to synzhronize the calls to iterator() method.

Correct working with Collections.synchronizedList

I am not sure how to properly use the Collections.synchronizedList() implementation.
I have these two:
public synchronized static List<CurrencyBox> getOrderList() {
return Collections.synchronizedList(orderList);
}
and
public static List<CurrencyBox> getOrderList() {
return Collections.synchronizedList(orderList);
}
So as far as I understood, synchronizedList really returns the orderList and not a copy, correct?
So If I want to gurantee atomic operations, like add and remove, which of the implementation above is correct?
And does something maybe changes with Java9? Or is it still the way to go or have you any other suggestion?
Thank you
Without context it's a bit hard to tell, from the snippets provided neither give you guaranteed atomic operations.
The documentation states:
Returns a synchronized (thread-safe) list backed by the specified
list. In order to guarantee serial access, it is critical that all
access to the backing list is accomplished through the returned list.
So even if you synchronize the method the best you'll get is a guarantee that no two objects are creating the synchronized list at the same time.
You need to wrap the original orderList with Collections.synchronizedList to begin with and return the stored result of that each time.
private static List<CurrencyBox> orderList = Collections.synchronizedList(new ArrayList<CurrencyBox>());
public static List<CurrencyBox> getOrderList() {
return orderList
}
A synchronized list only synchronized methods of this list.
It means a thread won't be able to modify the list while another thread is currently running a method from this list. The object is locked while processing method.
As an example, Let's say two threads run addAllon your list, with 2 different lists (A=A1,A2,A3, B=B1,B2,B3) as parameter.
As the method is synchronized, you can be sure those lists won't be merged randomly like A1,B1,A2,A3,B2,B3
You don't decide when a thread handover the process to the other thread so you can either get A1,A2,A3,B1,B2,B3 or B1,B2,B3,A1,A2,A3.
Credit : jhamon

synchronized collection getter

IIUC, a Collection that is only ever accessed by a synchronized method should be thread-safe - is that right?
e.g.,
class Foo {
private List<String> mList = new LinkedList<>();
public synchronized List<String> getList() {
return mList;
}
}
Assuming this getter is used exclusively to access the list - all operations are via getList() - it feels like it should be thread safe to me - but I'm very happy to be told I'm wrong.
TYIA
This would most likely not suffice as it simply returns a reference of the List; multiple threads would still be able to modify it concurrently, resulting in race conditions. If you're looking for a fully synchronized List, then I suggest using an ArrayList wrapped with Collections#synchronizedList.
Better you go for CopyOnWriteArrayList if you have much more reads than writes, Because its Synchronized and also the Iterator of CopyOnWriteArrayList is Fail-Safe and doesn't throw ConcurrentModificationException.
You can also make the existing list synchronized using Collections.synchronizedList(list) but the Iterator will be Fail-Fast.

What is the difference between using synchronizedCollection and just synchronized (collection)?

1.6 Javadoc is not clear on this. What is the difference between
List l = LinkedList();
synchronized (l) {
l.add... // do some work
l.set...
l.remove...
}
vs.
List l = LinkedList();
Collection c = Collections.synchronizedCollection (l);
synchronized (c) {
c.add...; c.set....; c.remove...
}
???
Why the need for a synchronizedCollection class? What is wrong with the first method?
What is wrong with the first method?
Nothing is wrong with it: as long as you synchronize all access, your program is going to perform as expected.
Why the need for a synchronizedCollection class?
In case you are going to use it inside a synchronized block, there's no reason indeed: the additional synchronization inside the collection is not going to lock other readers and writers, because synchronized block already does this.
The reason behind using synchronizedCollection in the first place is to avoid synchronized blocks. Calling add, set, and remove without synchronization will not leave your collection in an invalid state.
However, in the absence a synchronized block outside the statements, the three individual operations would not be executed as an atomic block.

3 threads with access to 1 object in java

I want to create a static arrayList for communication between 3 threads:
1. thread will add some data to list;
2. thread will remove data from list;
3. thread (timer every 3 sec) will check if size of list equals 0, and if no print all object of this list.
I'm wondereing what would happen if more than 1 thread will try to access this list at same time (for example timer will check size of list at same time when second thread will be removeing object from list).
I guess that i have to synchronize this list, but have no idea how to do that. Can you give me some advise?
I'm wondereing what would happen if more than 1 thread will try to
access this list at same time
Firstly ArrayList is not thread-safe, so you should not use it directly.
One possibility is to use Collections.synchronizedList(...); which provides you thread safety but will hamper concurrency.
Your requirement seems to be like a Queue, so you should use BlockingQueue for that, e.g LinkedBlockingQueue which is thread-safe.
NOTE:
Compound operations on list will still be unsafe if you use Collections.synchronizedList(...).
You can use
List myList = Collections.synchronizedList(new ArrayList());
ArrayList is not thread-safe. You will need to handle the synchronization by yourself or the results will be unpredictable.
As suggested in the related question: How do I make my arraylist thread safe you could use Collections.synchronizedList(...) to obtain a thread-safe version of your List
The javadoc gives an example of how to utilize the List returned by that method.
List list = Collections.synchronizedList(new ArrayList());
...
synchronized (list) {
Iterator i = list.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
Other solutions have already suggested this, but using this approach has a potential performance penalty since the synchronization blocks concurrent access to the List. This will ultimately limit the rate at which you are able to add & remove data from the backing List.
This code snippet will help you in the right direction
//have a lock Object
private static final Object lock = new Object();
// your list
private static List list = null
//synchronized on lock object. this will allow only one thread at a time
synchronized(lock){
//access,add to, remove from list
}
By this way, you can make sure there is only one thread at a time accessing your list
Better yet, using concurrency primitives (wait, notify, and synchronized) you can have the printing thread wait, and only wake up after one of the other threads actually changed the ArrayList. This has the advantage of not printing when there's no change, and being woken up immediately when a change happens. You may still get false wake-ups, but can be coded around if it's a problem.
In printing thread:
synchronized(lock)
{
while(true/*or some boolean to indicate you're done*/)
{
lock.wait();
//print list
}
}
In a thread that edits the list:
synchronized(lock)
{
//modify list
lock.notify();
}
You can also do lock.wait(3000); to print after 3 seconds anyway even if no change happens.

Categories

Resources