Using ConcurrentLinkedQueue with some non atomic operations - java

When we use one of the inbuilt queues like ConcurrentLinkedQueue or even some BlockingQueue, single calls are atomic and guaranteed to be thread safe.
But when of the 5 calls to the API, 4 calls are single, but one call is of the form:
if(some condition)
{
queue.call();
}
This call needs to be in a synchronized block since this operations is non atomic.
But doesn't introducing this call also means that all access to this queue, whether read or write should be synchronized from now on?
If yes, can I assume that once a single non atomic call creeps in the code, which is very likely, then all access to the fancy queue will have to be manually synchronized?

ConcurrentLinkedQueue doesn't make the quite the same atomic guarantees that you assume. From the javadoc:
Memory consistency effects: As with other concurrent collections,
actions in a thread prior to placing an object into a
ConcurrentLinkedQueue happen-before actions subsequent to the access
or removal of that element from the ConcurrentLinkedQueue in another
thread.
It's not the same as wrapping a LinkedList or something in a Collections.synchronizedList; different threads might see different answers to size(), for example, because it doesn't lock the collection.
Based on your comment you can probably replace the if statement with a single call to Queue's poll and check if the retrieved element is null.

Related

Java: What would happen if multiple threads are trying to access a queue implemented from LinkedList as opposed to ConcurrentLinkedQueue?

What would happen if multiple threads are trying to access a queue implemented from LinkedList as opposed to ConcurrentLinkedQueue?
Assuming that each thread only uses add() and poll() and no other function calls, are those two operations atomic?
If they are atomic, then is there a benefit in using ConcurrentLinkedQueue instead of a regular LinkedList implementation?
It's undefined. A regular LinkedList is not atomic / safe for a multi-threaded use.
You can wrap it in Collections.synchronizedList(LinkedList) to gain atomic operations but it's still different. ConcurrentLinkedQueue was specifically designed for use in a multi-threaded environment as "An unbounded thread-safe queue based on linked nodes". And you'll find several things it does differently if you read the documentation like
implementation employs an efficient non-blocking algorithm [...]
while a synchronized LinkedList locks the entire list for every operation. But it also has downsides like
Beware that, unlike in most collections, the size method is NOT a constant-time operation.
It depends on your requirements but if you want a concurrent queue, it's pretty safe to assume that you shouldn't use a LinkedList.
Those operations are not atomic.
Looking at the source for LinkedList you can see add and poll call routines that are most definitely not safe for two threads to be executing on the same instance without synchronization.

Can objects get lost if a LinkedList is add/remove fast by lots of threads?

sound like a silly question. I just started Java Concurrency.
I have a LinkedList that acts as a task queue and is accessed by multiple threads. They removeFirst() and execute it, other threads put more tasks (.add()). Tasks can have the thread put them back to the queue.
I notice that when there are a lot of tasks and they are put back to the queue a lot, the number of tasks I add to the queue initially are not what come out, 1, or sometimes 2 is missing.
I checked everything and I synchronized every critical section + notifyAll().
Already mark the LinkedList as 'volatile'.
Exact number is 384 tasks, each is put back 3072 times.
The problem doesn't occur if there is a small number of tasks & put back. Also if I System.out.println() all the steps then it doesn't happens anymore so I can't debug.
Could it be possible that LinkedList.add() is not fast enough so the threads somehow miss it?
Simplified code:
public void callByAllThreads() {
Task executedTask = null;
do
{
// access by multiple thread
synchronized(asyncQueue) {
executedTask = asyncQueue.poll();
if(executedTask == null) {
inProcessCount.incrementAndGet(); // mark that there is some processing going on
}
}
if(executedTask != null) {
executedTask.callMethod(); // subclass of task can override this method
synchronized(asyncQueue) {
inProcessCount.decrementAndGet();
asyncQueue.notifyAll();
}
}
}
while(executedTask != null);
}
The Task can override callMethod:
public void callMethodOverride() {
synchronized(getAsyncQueue()) {
getAsyncQueue().add(this);
getAsyncQueue().notifyAll();
}
}
From the docs for LinkedList:
Note that this implementation is not synchronized. If multiple threads access a linked list concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
i.e. you should synchronize access to the list. You say you are, but if you are seeing items get "lost" then you probably aren't synchronizing properly. Instead of trying to do that, you could use a framework class that does it for you ...
... If you are always removing the next available (first) item (effectively a producer/consumer implementation) then you could use a BlockingQueue implementation, This is guaranteed to be thread safe, and has the advantage of blocking the consumer until an item is available. An example is the ArrayBlockingQueue.
For non-blocking thread-safe queues you can look at ConcurrentLinkedQueue
Marking the list instance variable volatile has nothing to do with your list being synchronized for mutation methods like add or removeFirst. volatile is simply to do with ensuring that read/write for that instance variable is communicated correctly between, and ordered correctly within, threads. Note I said that variable, not the contents of that variable (see the Java Tutorials > Atomic Access)
LinkedList is definitely not thread safe; you cannot use it safely with multiple threads. It's not a question of "fast enough," it's a question of changes made by one thread being visible to other threads. Marking it volatile doesn't help; that only affects references to the LinkedList being changed, not changes to the contents of the LinkedList.
Consider ConcurrentLinkedQueue or ConcurrentLinkedDeque.
LinkedList is not thread safe, so yes, multiple threads accessing it simultaneously will lead to problems. Synchronizing critical sections can solve this, but as you are still having problems you probably made a mistake somewhere. Try wrapping it in a Collections.synchronizedList() to synchronize all method calls.
Linked list is not thread safe , you can use ConcurrentLinkedQueue if it fits your need,which seems possibly can.
As documentation says
An unbounded thread-safe queue based on linked nodes. This queue
orders elements FIFO (first-in-first-out). The head of the queue is
that element that has been on the queue the longest time. The tail of
the queue is that element that has been on the queue the shortest
time. New elements are inserted at the tail of the queue, and the
queue retrieval operations obtain elements at the head of the queue. A
ConcurrentLinkedQueue is an appropriate choice when many threads will
share access to a common collection. This queue does not permit null
elements.
You increment your inProcessCount when executedTask == null which is obviously the opposite of what you want to do. So it’s no wonder that it will have inconsistent values.
But there are other issues as well. You call notifyAll() at several places but as long as there is no one calling wait() that has no use.
Note further that if you access an integer variable consistently from inside synchronized blocks only throughout the code, there is no need to make it an AtomicInteger. On the other hand, if you use it, e.g. because it will be accessed at other places without additional synchronization, you can move the code updating the AtomicInteger outside the synchronized block.
Also, a method which calls a method like getAsyncQueue() three times looks suspicious to a reader. Just call it once and remember the result in a local variable, then everone can be confident that it is the same reference on all three uses. Generally, you have to ensure that all code is using the same list, hence the appropriate modifier for the variable holding it is final, not volatile.

ConcurrentHashMap operations

Following are some lines from the java docs of ConcurrentHashMap
This class obeys the same functional specification as Hashtable, and
includes versions of methods corresponding to each method of
Hashtable. However, even though all operations are thread-safe,
retrieval operations do not entail locking, and there is not any
support for locking the entire table in a way that prevents all
access.
What is the meaning of the statement
though all operations are thread-safe
from above paragraph?
Can anyone explain with any example of put() or get() methods?
The ConcurrentHashMap allows concurrent modification of the Map from several threads without the need to block them. Collections.synchronizedMap(map) creates a blocking Map which will degrade performance, albeit ensure consistency (if used properly).
Use the second option if you need to ensure data consistency, and each thread needs to have an up-to-date view of the map. Use the first if performance is critical, and each thread only inserts data to the map, with reads happening less frequently.
Your question is odd. If you understand what "thread safety" means then you would be able to understand how it applies to get() and put() on your own. If you don't understand thread safety then there is no point to explain it specifically in relation to get() and put(). Are you sure this isn't a homework question?
However, answering your question anyway, the fact that ConcurrentHashMap is thread safe means that if you have several threads executing put()s on the same map at the same time, then: a) no damage will occur to the internal data structures of the map and: b) some other thread doing a get() will see all of the values put in by the other threads. With a non-thread safe Map such as HashMap neither of those are guaranteed.

Why does the acquire() method in Semaphores not have to be synchronized?

I am getting into Semaphores in Java and was reading this article http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Semaphore.html . The only thing I don't get is why the acquire() method is not used in a synchronized context. Looking at the example from the above webiste:
They create a semaphore:
private Semaphore semaphore = new Semaphore(100);
and get a permit just like this:
semaphore.acquire();
Now, wouldn't it be possible that two or more threads try to acquire() at the same time? If so, there would be a little problem with the count.
Or, does the semaphore itself handle the synchronization?
Or, does the semaphore itself handle the synchronization?
Yes that's basically it. Semaphores are thread safe as explained in the javadoc:
Memory consistency effects: Actions in a thread prior to calling a "release" method such as release() happen-before actions following a successful "acquire" method such as acquire() in another thread.
Most operations on the objects in the java.util.concurrent package are thread safe. More details are provided at the very bottom of the package javadoc.
Semaphores ought to be fast and therefore use the atomic concurrency primitives from the Unsafe class, like CAS (compare and swap).
With these primitives synchronization happens on a much lower level and monitors are not needed. (Lock-free synchronization).
In fact the synchronization is performed by a loop continously using CAS until the expected value equals the written/read value.
synchronization is guaranteed by AbstractQueuedSynchronizer with CAS operations
see the javadoc here

Synchronizing in a for each loop still throws ConcurrentModificationExceptions

I'm trying to iterate through a loop on one thread, like so:
for (UnitTask task : chain) {
g.drawLine((int) task.getLocation().getX(), (int) task.getLocation().getY(), (int) currentPos.getX(), (int) currentPos.getY());
g.fillOval((int) task.getLocation().getX() - 2, (int) task.getLocation().getY() - 2, 5, 5);
currentPos = task.getLocation();
}
However, I have another thread (the Swing event thread) which can add to this object. Hence, ConcurrentModificationException. I tried obtaining a lock by surrounding the code with synchronized (chain) { ... }, but I still get the errors.
As a bit of a Java synchronization newbie, I'm a little confused as to why. I would expect this to make the loop thread-safe, but evidently, it is not.
Interestingly, chain is an instance of a custom class, but it is only a thin wrapper around a LinkedList. The list itself is private, and there's no way for an external class to retrive it directly (there are methods to explicitly add/remove objects), so I wouldn't expect this to affect the outcome.
The meaning of
synchronized (c) {
... code that uses c ...
}
is
wait for c to be unlocked
lock c
execute the body
unlock c
So if you synchronize in your thread, then your thread will wait for c to be unlocked and then dive in.
Now, if you do not synchronize the code on the other thread that modifies c, that code is going to just go ahead and modify c without waiting for a lock. Synchronizing a block in one thread does not make another thread wait for a lock. If the other thread has a line such as
c.add(someOtherTask)
that is not in a synchronized block, then it's going to do the add no matter what. This is the cause of your exception. It is also the reason why you saw the exception even though you put the code in your thread in a synchronized block: your code was "playing by the rules" but the other thread couldn't have cared less.
Be careful about synchronizing long-running code though. You are better off, as Stephen C says, to use a concurrent collection type.
Synchronization will not necessarily help.
Basically the problem is that you are using a collection type that does not allow the collection to be modified while an iteration is in progress (except via the iterator's remove method ... if supported). This is not a threading / synchronization issue per se. (And if you try to solve it simply by synchronization, you may introduce another problem.)
If you want to be able to iterate and modify at the same time, you will need to use a different collection type such as ConcurrentLinkedDeque instead of LinkedList.
If the iteration and writing are happening on separate threads, then shouldn't synchronizing block the writing until the iteration is finished? Or am I missing something?
The problem will be in how you have implemented the synchronization:
If you are not explicitly doing some kind synchronization in your LinkedList version, then no synchronization is done for you.
If you use a synchronization wrapper created by one of the Collections.synchronizedXxx methods, then the javadocs for those methods clearly state that an Iterator object returned by the wrapper's iterator() method IS NOT synchronized.
If you are doing the synchronization by hand, then you have to make sure that everything is synchronizing on the same mutex. And that lock has to be held on that mutex for the duration of the iteration ... not just for the call the iterator().
And note that if you hold a lock for a long time (e.g. while you are iterating a long list), this can potentially block other threads that need to update the list for a long time. That kind of thing can be a concurrency bottleneck that can (in the worst case) reduce your system's performance to the speed of a single processor.
The ConcurrentXxx classes typically avoid this by relaxing the consistency guarantees for the sequences produced by the iterators. For instance, you may not see elements that were added to the collection after you started the iteration.

Categories