1]What is Non-blocking Concurrency and
how is it different.
As others have mentioned, Non-blocking is a way of saying deadlock-free (meaning we shouldn't have a condition where progress halts entirely while threads are blocked, waiting for access).
What is meant by 'concurrency' is just that multiple computations are happening at the same time (concurrently).
2] I have heard that this is available
in Java. Are there any particular
scenarios we should use this feature
You want to use non-blocking algorithms when it is important that multiple threads can access the same resources concurrently, but we aren't as concerned with the order of access or the possible ramifications of interleaving action (more on this below).
3] Is there a difference/advantage of
using one of these methods for a
collection. What are the trade offs
.
Using the synchronized(list) block ensures that all of the actions performed within the block are seen as atomic. That is to say, as long as we only access the list from synchronized(list) blocks, all updates to the list will appear as if they happened at the same time within the block.
A synchronizedList (or synchronizedMap) object only ensures that individual operations are thread-safe. This means that two inserts will not occur concurrently. Consider the following loop:
for(int i=0; i < 4; i++){
list.add(Integer.toString(i));
}
If the list in use was a synchronizedList and this loop was executed on two different threads, then we may end up with {0,0,1,2,1,3,2,3} in our list, or some other permutation.
Why? Well, we are guaranteed that thread 1 will add 0-3 in that order and we are guaranteed the same of thread 2, however we have no guarantee of how they will interleave.
If, however, we wrapped this list in a synchronized(list) block:
synchronized(list){
for(int i=0; i < 4; i++){
list.add(Integer.toString(i));
}
}
We are guaranteed that the inserts from thread 1 and thread 2 will not interleave, but they will occur all at once. Our list will contain {0,1,2,3,0,1,2,3}. The other thread will block, waiting on list, until the first thread completes. We have no guarantee which thread will be first, but we are guaranteed it will finish before the other begins.
So, some trade-offs are:
- With a syncrhonizedList, you can
insert without explicitly using a
synchronized block.
- A syncrhonizedList might give you a
false sense of security, since you
may naively believe successive
opertaions on one thread to be
atomic, when only individual
operations are atomic
- Using a syncrhonized(list) block must be done with care, because we are in a position to create deadlock (more below).
We can create a deadlock when two (or more) threads are each waiting for a subset of resources held by another. If, for example, you had two lists: userList and movieList.
If thread 1 first acquires the lock to userList, then movieList, but thread two performs these steps in reverse (acquires the lock to movieList before userList), then we have opened ourself up for deadlock. Consider the following course of events:
- Thread 1 gets lock to userList
- Thread 2 gets lock to movieList
- Thread 1 tries to get lock to movieList, waits on Thread 2 to release
- Thread 2 tries to get lock to userList, waits on Thread 1 to release
Both threads are waiting for the other and neither can move forward. This is a blocking scenario, and since neither will relinquish its resource, we are deadlocked.