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

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.

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.

synchronized ArrayList vs synchronized method block

I have 2 code snippets which will do the same thing which makes thread safe. first one does it using Collections.synchronizedList, Example:
DataServiceRequest request = Collections.synchronizedList(new ArrayList<DataServiceRequest>());
Second one do the same thing by synchronizing the method, Example:
public synchronized void addRequest(DataServiceRequest request) {
this.getRequests().add(request);
}
What would be the most efficient and safest way When comparing with performance from above 2 examples?
The first is really just syntactic sugar for the second (it returns a wrapper list that puts synchronized (mutex) around each call), so it is unlikely to make any difference from a performance point of view.
As for "which is the safest way" - that depends on your coding standards. You must pay attention to the documents for Collections.synchronizedList if you use it, particularly:
it is critical that all access to the backing list is accomplished through the returned list.
and
It is imperative that the user manually synchronize on the returned list when iterating over it
You'll still have the same issue when iterating a list that you control the synchronization of - this is just saying that the mutex in use for synchronizedList is the list itself. If you control the synchronization you just need to consistently use the same mutex for all thread-safe access to the backing list.
Your question might imply that you don't plan to synchronize on all list operations, not just those that change the list. If so, then this would be wrong thinking. But even if not so, using synchronizedList wrapper takes that worry away from your program because it guarantees that all method calls are synchronized.
The one thing that synchronizedList cannot guarantee is synchronization over the block of code which consumes a list iterator. This is still something you'll need to do inside your own synchronized block.

Can synchronized methods serve all purposes which a synchronized block can?

Suppose i have a code snippet where i want to insert a node in a Linked List and for consistency i used following coding mechanism : Assume that current and next are elements of LinkedList where current represent the Object we are working on and next represent the next object of List.
synchronized(current) {
synchronized(next) {
.............
}
}
and i performed an insertafter for current Object. Can the same functionality be achieved through synchronized methods. Since we can obtain lock only on a single object. So synchronized insertAfter wont prevent someone to use insertBefore.
A synchronized method is nothing but syntactic sugar for synchronized(this) {...}.
So the literal answer to your question is "not easily". You would need two different objects where the two synchronized methods are declared, and call one from the other. But it seems like a bad idea.
In general, I question the goal of trying to reduce an explicit synchronized block to a synchronized method. Synchronized blocks are more readable, and let you encapsulate the lock object to prevent undesired lock contention if some other code decides to use the same instance as the lock for some reason.
Also, are you sure you need the kind of fine-grained locking you're trying to do? This seems error-prone... a more straightforward code would synchronize on the same object for any operation on the list.
This pattern is well know to result in what is called deadly embrace. Imagine someone else making use of your code and also doing the equivalent of an insertBefore:
synchronized(next) {
synchronized(current) {
.............
}
}
This would obviously end in tears.
The obvious answer is not to synchronize on the nodes but on the joins between the nodes.

Java synchronized - am I doing it right?

I'm not used to working with synchronized. Does the following snippet look right?
public void setNewSessionListener(NewSessionListener newSessionListener) {
if (this.newSessionListener != null)
synchronized (this.newSessionListener) {
this.newSessionListener = newSessionListener;
}
else
this.newSessionListener = newSessionListener;
}
More specifically do I need to perform a null check? I have a gut feeling there is something fundamentally wrong with that code.
There are two mistakes. The first one is that if you access a field which requires synchronization, you always have to access it with the same lock held. Also you have to check if the field is null and write to the field in the same sychronized block, because otherwise when you write something to the field, it may already be not null.
The second one is that it is best to sychronize on something that doesn't change, in other words, on a static final field or on the instance itself. For example, you can create a lock object specifically for this purpose:
private static final Object LOCK = new Object();
And then you will write:
synchronized (LOCK) {
if (this.newSessionListener == null) this.newSessionListener = newSessionListener;
}
Your feeling is right. You should do the null check inside the synchronized block. Otherwise the block won't prevent double initialization. Furthermore, you shouldn't synchronize on this.newSessionListener which you are about to change - choose an object (reference) which is going to stay around for the whole scope of the block. This is the only way to guarantee that only one thread can enter this block of code at any point in time. The typical way to achieve this is to synchronize on this. Alternatively, you may synchronize on a private final object, kept for this sole purpose.
Moreover, ultimately you are performing the same assignment in both the if and the else branches, which is probably not what you want.
This is, at a minimum, a very bad idea. You are synchronizing on an object you then assign to.
Because you are using synchronized I assume this is called asynchronously and it could be called by one thread while another thread is inside this code. If so, you are not locking on a common object, you are locking on the value it is holding at that point in time.
Probably, and I stress probably, you can do synchronized (this). That will insure that all calls to this method for this specific object are synchronized. And that calls to other instances of this class are locked for that other object - but not across instances.
If you want to synchronize across all instantiated objects, call synchronized (YourClass)
Here's another possibility (i tend to prefer explicit locks over the synchronized block):
private ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// do your synchronized code here.
}
finally {
lock.unlock();
}
Though just by looking at your code, i'm not sure why there's even an if block. Why are you synchronized in one case, and not the other? Especially considering you're making the same assignment in either case?

synchronizedCollection and contains--do I need to synchronize manually?

I'm using Collections.synchronizedCollection in Java to protect a Set that I know is getting accessed concurrently by many threads. The Java API warns:
" It is imperative that the user manually synchronize on the returned collection when iterating over it:
Collection c = Collections.synchronizedCollection(myCollection);
...
synchronized(c) {
Iterator i = c.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
"
If I use c.contains(obj), is that thread-safe? Internally, obviously, this is iterating over the Collection and seeing if any of the objects in it are equal to obj. My instinct is to assume that this is probably synchronized (it would seem to be a major failing if not), but given previous pains with synchronization, it seems wise to double-check, and a Google search for answers on this hasn't turned up anything.
In itself, a call to contains is safe.
The problem is that one often tests whether a collection contains an element then does something to the collection based on the result.
Most likely, the test and the action should be treated as a single, atomic operation. In that case, a lock on the collection should be obtained, and both operations should be performed in the synchronized block.
Collections.synchronizedCollection() will return a thread safe collection which means
any single method call is thread safe by itself. It depends what you want do. If you want to call couple of methods, java cannot make it thread safe together.
It's safe, because contains itself is synchronized.

Categories

Resources