How to use ConcurrentLinkedQueue? - java

How do I use a ConcurrentLinkedQueue in Java?
Using this LinkedQueue, do I need to be worried about concurrency in the queue? Or do I just have to define two methods (one to retrive elements from the list and another to add elements to the list)?
Note: obviously these two methods have to be synchronized. Right?
EDIT: What I'm trying to do is this: I have a class (in Java) with one method to retrieve items from the queue and another class with one method to add items to the queue. The items added and retrieved from the list are objects of my own class.
One more question: do I need to do this in the remove method:
while (queue.size() == 0){
wait();
queue.poll();
}
I only have one consumer and one producer.

No, the methods don't need to be synchronized, and you don't need to define any methods; they are already in ConcurrentLinkedQueue, just use them. ConcurrentLinkedQueue does all the locking and other operations you need internally; your producer(s) adds data into the queue, and your consumers poll for it.
First, create your queue:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
Now, wherever you are creating your producer/consumer objects, pass in the queue so they have somewhere to put their objects (you could use a setter for this, instead, but I prefer to do this kind of thing in a constructor):
YourProducer producer = new YourProducer(queue);
and:
YourConsumer consumer = new YourConsumer(queue);
and add stuff to it in your producer:
queue.offer(myObject);
and take stuff out in your consumer (if the queue is empty, poll() will return null, so check it):
YourObject myObject = queue.poll();
For more info see the Javadoc
EDIT:
If you need to block waiting for the queue to not be empty, you probably want to use a LinkedBlockingQueue, and use the take() method. However, LinkedBlockingQueue has a maximum capacity (defaults to Integer.MAX_VALUE, which is over two billion) and thus may or may not be appropriate depending on your circumstances.
If you only have one thread putting stuff into the queue, and another thread taking stuff out of the queue, ConcurrentLinkedQueue is probably overkill. It's more for when you may have hundreds or even thousands of threads accessing the queue at the same time. Your needs will probably be met by using:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
A plus of this is that it locks on the instance (queue), so you can synchronize on queue to ensure atomicity of composite operations (as explained by Jared). You CANNOT do this with a ConcurrentLinkedQueue, as all operations are done WITHOUT locking on the instance (using java.util.concurrent.atomic variables). You will NOT need to do this if you want to block while the queue is empty, because poll() will simply return null while the queue is empty, and poll() is atomic. Check to see if poll() returns null. If it does, wait(), then try again. No need to lock.
Finally:
Honestly, I'd just use a LinkedBlockingQueue. It is still overkill for your application, but odds are it will work fine. If it isn't performant enough (PROFILE!), you can always try something else, and it means you don't have to deal with ANY synchronized stuff:
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();
queue.put(myObject); // Blocks until queue isn't full.
YourObject myObject = queue.take(); // Blocks until queue isn't empty.
Everything else is the same. Put probably won't block, because you aren't likely to put two billion objects into the queue.

This is largely a duplicate of another question.
Here's the section of that answer that is relevant to this question:
Do I need to do my own synchronization if I use java.util.ConcurrentLinkedQueue?
Atomic operations on the concurrent collections are synchronized for you. In other words, each individual call to the queue is guaranteed thread-safe without any action on your part. What is not guaranteed thread-safe are any operations you perform on the collection that are non-atomic.
For example, this is threadsafe without any action on your part:
queue.add(obj);
or
queue.poll(obj);
However; non-atomic calls to the queue are not automatically thread-safe. For example, the following operations are not automatically threadsafe:
if(!queue.isEmpty()) {
queue.poll(obj);
}
That last one is not threadsafe, as it is very possible that between the time isEmpty is called and the time poll is called, other threads will have added or removed items from the queue. The threadsafe way to perform this is like this:
synchronized(queue) {
if(!queue.isEmpty()) {
queue.poll(obj);
}
}
Again...atomic calls to the queue are automatically thread-safe. Non-atomic calls are not.

This is probably what you're looking for in terms of thread safety & "prettyness" when trying to consume everything in the queue:
for (YourObject obj = queue.poll(); obj != null; obj = queue.poll()) {
}
This will guarantee that you quit when the queue is empty, and that you continue to pop objects off of it as long as it's not empty.

Use poll to get the first element, and add to add a new last element. That's it, no synchronization or anything else.

The ConcurentLinkedQueue is a very efficient wait/lock free implementation (see the javadoc for reference), so not only you don't need to synchronize, but the queue will not lock anything, thus being virtually as fast as a non synchronized (not thread safe) one.

Just use it as you would a non-concurrent collection. The Concurrent[Collection] classes wrap the regular collections so that you don't have to think about synchronizing access.
Edit: ConcurrentLinkedList isn't actually just a wrapper, but rather a better concurrent implementation. Either way, you don't have to worry about synchronization.

Related

Does using a LinkedBlockingQueue between two threads mean we don't need to synchronize their access to shared data?

I have a situation where a project I'm maintaining contains a piece of code where:
A thread T1 periodically updates a field of type List<String> then adds a value to a LinkedBlockingQueue:
// ctor
List<String> list = null;
queue = new LinkedBlockingQueue(); // Integer.MAX_VALUE capacity
// Thread T1
list = getNewList();
queue.offer(/* some value */);
Another thread T2 periodically polls queue and, upon receiving a certain value, reads list:
// Thread T2
Object value = queue.poll();
if (Objects.equals(value, /* some desired value */) {
// Read `list` in (1)
}
The thing that caught my attention was the lack of synchronization between the two threads as they accessed list (was not marked volatile either), which made me think there could be a data race in that code. However, when I referred to BlockingQueue, I found a sentence that says:
Memory consistency effects: As with other concurrent collections, actions in a thread prior to placing an object into a BlockingQueue happen-before actions subsequent to the access or removal of that element from the BlockingQueue in another thread.
Does this mean that T2 is always guaranteed to observe the changes made by T1 to list and no data race is possible?
It's a particular instance of an effect that's more generally described here (the memory consistency errors link on that page is especially worth reading.
All of these collections help avoid Memory Consistency Errors by defining a happens-before relationship between an operation that adds an object to the collection with subsequent operations that access or remove that object.
So, more generally, when you have two pieces of code like this:
// list is a non thread safe ArrayList
list.add("abcd");
// col is *any* java.util.concurrent collection
col.add(anObject); // or put, or offer...
and
if (col.get() == anObject) { … } // or poll etc.
If the second piece of code is executed by other thread than the first piece (and the condition is true), any code placed after the retrieval of anObject can see "abcd" added to the list.
But:
it has to be the same object (anObject, the stuff you put/get from concurrent collection)
it's assuming after col.addObject(anObject) call, the list wasn't further modified
it (obviously, but worth noting) has to have been actually put into the collection. offer() might have returned false in that other thread and poll() might have timed out in this one.
Does this mean that T2 is always guaranteed to observe the changes made by T1 to list and no data race is possible?
You are protected by the memory model in the sense that the changes to the list BEFORE ADDING TO THE QUEUE will be visible to the second thread before the second thread sees them.
Otherwise these Queue's won't be very useful.
But for any changes done later. All bets are off.
Periodic Updates
You said: T1 periodically updates a field of type List and then adds it to the queue.
If by field you mean some instance variable or static variable.
And by periodically, you mean that you mutate it from T1 after you have put it in the queue.
Then I'd say that you most definitely are going to have trouble. The best course of action would be to send a COPY of the list like this:
list = getNewList();
queue.offer(new ArrayList<String>(list));
Its best you aren't sharing objects between the threads. Just create it and send it.
In fact, it doesn't make sense to send a shared list through the queue. You might as well just share it all the time (in some protected fashion).
The reason you use a queue is that you want to send a message to the other thread, and at that point you should release it, and do nothing else.
Memory model
Again, the memory model will guarantee that the object is good once it gets to the other thread. So visibility won't be a problem as long as T1 (or any other thread) no longer does anything to the object.
Note on live objects
Regardless of what you do, beware of queueing "live objects" like Hibernate controlled objects and things that are intended to live for a very short time. When I've used this feature I generally send over id's and things like that so T2 can restore the object from the database independently and not hang on to objects that were managed in another thread.
So you need to be careful about what you put in the list as well. Immutable strings are ok, of course.

Is synchronized enough to make the drainTo() method of a BlockingQueue atomic?

If I simply do something like this:
synchronized(taskQueue) { //taskQueue is a BlockingQueue
taskQueue.drainTo(tasks); //tasks is a list
}
Am I assured that concurrent calls to taskQueue.put() and taskQueue.take() can not be executed inside the synchronized block?
In other words, am I making the drainTo() method atomic?
Or more generally, how do I make a composition of thread safe operations atomic?
Example:
if(taskQueue.size() == 1) {
/*Do a lot of things here, but I do not want other threads
to change the size of the queue here with take or put*/
}
//taskQueue.size() must still be equal to 1
See below excerpt from Java docs of BlockingQueue
BlockingQueue implementations are thread-safe. All queuing methods achieve their effects atomically using internal locks or other forms
of concurrency control. However, the bulk Collection operations
addAll, containsAll, retainAll and removeAll are not necessarily
performed atomically unless specified otherwise in an implementation.
So it is possible, for example, for addAll(c) to fail (throwing an
exception) after adding only some of the elements in c.
Also, check the example which shows that a BlockingQueue implementation can safely be used with multiple producers and multiple consumers.
So, if you are not using bulk Collection operations like addAll, containsAll, retainAll and removeAll then you are thread safe.
You even don't need synchronized(taskQueue) { and can directly use taskQueue.drainTo(tasks); because BlockingQueue implementations are thread-safe for non-bulk-collection operations like put, take, drainTo etc.
Hope this helps!
Take a LinkedBlockingQueue as an example, it has a 'takeLock' and 'putLock' which are its member variables.
So client side synchronization dose not help here, since other 'take' actions are not guarded by this lock, even if this lock comes from the queue itself.
The drainTo() method is guarded by 'takeLock', for any other 'take' operation it's thread safe. But for the 'put' operations, they are guarded by 'putLock', so will not be affected.
So I think nothing is needed here!

Do I need to synchronize my calls to BlockingQueue (java)?

I want to store a list of objects in a thread safe manner, while maintaining priority. Originally I started out using a BlockingQueue for this as it's thread safe and has ability to maintain custom priority.
I'm wondering if I need to synchronize my methods? My code looks like:
void addToQueue(SomeObject obj) {
... put it on my priority queue
... do some logging
}
What I have noticed is the logging is happening out of order, when accessing addToQueue from multiple threads. So I wrapped my method like so:
void addToQueue(SomeObject obj) {
syncronized(myMutex) {
... put it on my priority queue
... do some logging
}
}
This seemed to keep the logging in order. So now I've come to the conclusion that if I'm going this route, then maybe my code would be more efficient by not using a BlockingQueue but instead use a Set or List and manage the priority myself.
Maybe I have some misunderstanding of the BlockingQueue.
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
This is the javadoc for BlockingQueue. You use it if you need this blocking behavior, otherwise you don't.
BlockingQueue does not maintain any priority, it is strictly first-in-first-out. Perhaps you are using PriorityBlockingQueue?
Coming to your pseudocode:
void addToQueue(SomeObject obj) {
... put it on my priority queue
... do some logging
}
The queue is thread-safe, but that only means that multiple threads can concurrently call put it on my priority queue without any data corruption. It does not guarantee any of the following:
If there are multiple threads blocked which one will succeed first
If a thread X completes the put before a thread Y then thread X will also complete the logging before thread Y.
If you need all of addToQueue occur without interleaving from other threads then you need to synchronize. Note that you can use the queue object itself:
void addToQueue(SomeObject obj) {
synchronized (queue) {
... put it on my priority queue
... do some logging
}
}
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html
As with other concurrent collections, actions in a thread prior to placing an object into a BlockingQueue happen-before actions subsequent to the access or removal of that element from the BlockingQueue in another thread.
If you want to use that safety to get ordered logging you have to log before putting items into the queue and after taken an item from the queue.
I wouldn’t use synchronized for getting ordered logging. Multi-threading means parallel execution and that implies that certain actions don’t have an ordering. Log Records can have a time-stamp and seeing them in the wrong order, i.e. in the console, looks like a minor glitch to me that is not worth sacrificing the advantages of parallel execution for.

Sync block required for Collections.synchronizedList.add()?

My understanding of this is that a synchronized block keeps other threads from accessing until such time as that block terminates; that is, they are put on hold till then via a lock held by the currently executing class (?).
So I wrap a for block which iterates over a list and then calls clear() on that list directly thereafter, in a synchronized block. as I can't afford to have other threads adding to the list between those two sets of operations. This is in accordance with the docs, which say,
It is imperative that the user manually synchronize on the returned
collection when iterating over it...
However I can't figure for sure whether I need to do the same when I am adding to the list. I am guessing not, since in my case the order of add operations from different threads is not important. I guess that what I'm unsure of is whether unsynchronized modify operations might have any negative impacts?
You only need locking when you have multiple operations which must work together. In the case of an Iterator, you will perform any operations over the life of the loop.
If adds can occur in any order, no additional locking is required.
I wrap a for block which iterates over a list and then calls clear()
From your use case, it sounds like a BlockingQueue (is thread safe without synchronized) or even an ExecutorService (which combines a thread pool with a queue) would be a better choice.
It is important that you synchronize on Collection itself
Collection c = Collections.synchronizedCollection(myCollection);
...
synchronized (c) {
for(Object o : c) {
....
}
other threads calling any methods of c will be blocked until you leave the block. No other synchronization is necessary

When should I use SynchronousQueue over LinkedBlockingQueue

new SynchronousQueue()
new LinkedBlockingQueue(1)
What is the difference? When I should use SynchronousQueue against LinkedBlockingQueue with capacity 1?
the SynchronousQueue is more of a handoff, whereas the LinkedBlockingQueue just allows a single element. The difference being that the put() call to a SynchronousQueue will not return until there is a corresponding take() call, but with a LinkedBlockingQueue of size 1, the put() call (to an empty queue) will return immediately.
I can't say that i have ever used the SynchronousQueue directly myself, but it is the default BlockingQueue used for the Executors.newCachedThreadPool() methods. It's essentially the BlockingQueue implementation for when you don't really want a queue (you don't want to maintain any pending data).
As far as I understand code above do the same things.
No, the code is not the same at all.
Sync.Q. requires to have waiter(s) for offer to succeed. LBQ will keep the item and offer will finish immediately even if there is no waiter.
SyncQ is useful for tasks handoff. Imagine you have a list w/ pending task and 3 threads available waiting on the queue, try offer() with 1/4 of the list if not accepted the thread can run the task on its own. [the last 1/4 should be handled by the current thread, if you wonder why 1/4 and not 1/3]
Think of trying to hand the task to a worker, if none is available you have an option to execute the task on your own (or throw an exception). On the contrary w/ LBQ, leaving the task in the queue doesn't guarantee any execution.
Note: the case w/ consumers and publishers is the same, i.e. the publisher may block and wait for consumers but after offer or poll returns, it ensures the task/element is to be handled.
One reason to use SynchronousQueue is to improve application performance. If you must have a hand-off between threads, you will need some synchronization object. If you can satisfy the conditions required for its use, SynchronousQueue is the fastest synchronization object I have found. Others agree. See: Implementation of BlockingQueue: What are the differences between SynchronousQueue and LinkedBlockingQueue
[Just trying to put it in (possibly) more clearer words.]
I believe the SynchronousQueue API docs states things very clearly:
A blocking queue in which each insert operation must wait for a corresponding remove operation by another thread, and vice versa.
A synchronous queue does not have any internal capacity, not even a capacity of one. You cannot peek at a synchronous queue because an element is only present when you try to remove it; you cannot insert an element (using any method) unless another thread is trying to remove it; you cannot iterate as there is nothing to iterate.
The head of the queue is the element that the first queued inserting thread is trying to add to the queue; if there is no such queued thread then no element is available for removal and poll() will return null.
And BlockingQueue API docs:
A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.
So the difference is obvious and somewhat critically subtle, especially the 3rd point below:
If the queue is empty when you are retrieving from BlockingQueue, the operation block till the new element is inserted. Also, if the queue is full when you are inserting in the BlockingQueue, the operation will block till the element is removed from the queue and a space is made for the new queue. However note that in SynchronousQueue, as operation is blocked for opposite operation (insert and remove are opposite of each other) to occur on another thread. So, unlike BlockingQueue, the blocking depends on the existence of the operation, instead of existence or non existence of an element.
As the blocking is dependent on existence of opposite operation, the element never really gets inserted in the queue. Thats why the second point: "A synchronous queue does not have any internal capacity, not even a capacity of one."
As a consequence, peek() always returns null (again, check the API doc) and iterator() returns an empty iterator in which hasNext() always returns false. (API doc). However, note that the poll() method neatly retrieves and removes the head of this queue, if another thread is currently making an element available and if no such thread exists, it returns null. (API doc)
Finally, a small note, both SynchronousQueue and LinkedBlockingQueue classes implement BlockingQueue interface.
SynchronousQueue works in a similar fashion with following major differences:
1) The size of SynchronousQueue is 0
2) put() method will only insert an element if take() method will be able to fetch that element from the queue at the same moment i.e. an element cannot be inserted if the consumer take() call is going to take some time to consume it.
SynchronousQueue - Insert only when someone will receive it at that moment itself.
Synchronous queues are basically used for handoff purposes. They do not have any capacity and a put operation is blocked until some other thread performs get operation.
If we want to safely share a variable between two threads, we can put that variable in synchrounous queue and let other thread take it from the queue.
Code Sample from https://www.baeldung.com/java-synchronous-queue
ExecutorService executor = Executors.newFixedThreadPool(2);
SynchronousQueue<Integer> queue = new SynchronousQueue<>();
Runnable producer = () -> {
Integer producedElement = ThreadLocalRandom
.current()
.nextInt();
try {
queue.put(producedElement);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
};
Runnable consumer = () -> {
try {
Integer consumedElement = queue.take();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
};
executor.execute(producer);
executor.execute(consumer);
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
executor.shutdown();
assertEquals(queue.size(), 0);
They are also used in CachedThreadPool to achieve an effect of unlimited(Integer.MAX) thread creation as tasks arrive.
CachedPool has coreSize as 0 and maxPoolSize as Integer.MAX with synchronous queue
As tasks arrive onto queue, other tasks are blocked until the first one is fetched out. Since it does not have any queue capacity, thread pool will create one thread and this thread will take out task allowing more tasks to be put onto the queue. This will continue until thread creation reaches maxPoolSize. Based on timeOut, idle threads maybe terminated and new ones are created without crossing the maxPoolSize.

Categories

Resources