Two BlockingQueue - deadlock - java

I have a requirement to manipulate two queues atomically and am not sure what is the correct synchronization strategy: This is what I was trying:
public class transfer {
BlockingQueue firstQ;
BlockingQueue secondQ;
public moveToSecond() {
synchronized (this){
Object a = firstQ.take();
secondQ.put(a)
}
}
public moveToFirst() {
synchronized(this) {
Object a = secondQ.take();
firstQ.put(a);
}
}
}
Is this the correct pattern? In the method moveToSecond(), if firstQ is empty, the method will wait on firstQ.take(), but it still holds the lock on this object. This will prevent moveToFirst() to have a chance to execute.
I am confused about the lock release during a wait - Does the thread release all locks [both this and BlockedQUeue lock?]? What is the correct pattern to provide atomicity dealing with multiple blocking queues?

You are using the correct approach using a common mutex to synchronize between both queues. However, to avoid the situation you describe with the first queue being empty I'd suggest reimplementing moveToFirst() and moveToSecond() to use poll() rather than take(); e.g.
public void boolean moveToFirst() {
// Synchronize on simple mutex; could use a Lock here but probably
// not worth the extra dev. effort.
synchronzied(queueLock) {
boolean success;
// Will return immediately, returning null if the queue is empty.
Object o = firstQ.poll();
if (o != null) {
// Put could block if the queue is full. If you're using a bounded
// queue you could use add(Object) instead to avoid any blocking but
// you would need to handle the exception somehow.
secondQ.put(o);
success = true;
} else {
success = false;
}
}
return success;
}

Another failure condition you didn't mention is if firstQ is not empty but secondQ is full, the item will be removed from firstQ but there will be no place to put it.
So the only correct way is to use poll and offer with timeouts and code to return things to the way they were before any failure (important!), then retry after a random time until both poll and offer are successful.
This is an optimistic approach; efficient in normal operation but quite inefficient when deadlocks are frequent (average latency depends on the timeout chosen)

You should use the Lock-mechanism from java.util.concurrency, like this:
Lock lock = new ReentrantLock();
....
lock.lock();
try {
secondQ.put(firstQ.take());
} finally {
lock.unlock();
}
Do the same for firstQ.put(secondQ.take()), using the same lock object.
There is no need to use the lowlevel wait/notify methods on the Object class anymore, unless you are writing new concurrency primitives.

In your code, while the thread is blocked on BlockingQueue.take() it is holding on to the lock on this. The lock isn't released until either the code leaves the synchronized block or this.wait() is called.
Here I assume that moveToFirst() and moveToSecond() should block, and that your class controls all access to the queues.
private final BlockingQueue<Object> firstQ = new LinkedBlockingQueue();
private final Semaphore firstSignal = new Semaphore(0);
private final BlockingQueue<Object> secondQ = LinkedBlockingQueue();
private final Semaphore secondSignal = new Semaphore(0);
private final Object monitor = new Object();
public void moveToSecond() {
int moved = 0;
while (moved == 0) {
// bock until someone adds to the queue
firstSignal.aquire();
// attempt to move an item from one queue to another atomically
synchronized (monitor) {
moved = firstQ.drainTo(secondQ, 1);
}
}
}
public void putInFirst(Object object) {
firstQ.put(object);
// notify any blocking threads that the queue has an item
firstSignal.release();
}
You would have similar code for moveToFirst() and putInSecond(). The while is only needed if some other code might remove items from the queue. If you want the method that removes on the queue to wait for pending moves, it should aquire a permit from the semaphore, and the semaphore should be created as a fair Semaphore, so the first thread to call aquire will get released first:
firstSignal = new Semaphore(0, true);
If you don't want moveToFirst() to block you have a few options
Have the method do do its work in a Runnable sent to an Executor
Pass a timeout to moveToFirst() and use BlockingQueue.poll(int, TimeUnit)
Use BlockingQueue.drainTo(secondQ, 1) and modify moveToFirst() to return a boolean to indicate if it was successful.
For the above three options, you wouldn't need the semaphore.
Finally, I question the need to make the move atomic. If multiple threads are adding or removing from the queues, then an observing queue wouldn't be able to tell whether moveToFirst() was atomic.

Related

Java wait() and notifyAll() resume oldest Thread

My problem:
Lets say that i have class A with some variable a
And class B with variables prev and next
In class A i want to make method changeIfEqual(B myB) which checks if A.a == my_B.prev, if so i change A.a to my_B.next. But if A.a != my_B.prev i want thread to wait() until continion is true and then execute the thread that have been waining for the longest time.
So I imagine A.changeIfEqual(B myB) should look like this:
public synchronized void changeIfEqual(B myB){
while(this.a != myB.b_prev){
wait();
}
notifyAll();
}
In this case the problem is how can I ensure that the oldest thread would be resume? (wait() and notifyAll() dont provide that)
You don’t. Which thread gets notified is up to the scheduler. If you replace the implicit locking (using synchronized) with ReentrantLock, then you can specify that the lock is fair. But that's not a perfect solution, see the API docs:
The constructor for this class accepts an optional fairness parameter. When set true, under contention, locks favor granting access to the longest-waiting thread. Otherwise this lock does not guarantee any particular access order. Programs using fair locks accessed by many threads may display lower overall throughput (i.e., are slower; often much slower) than those using the default setting, but have smaller variances in times to obtain locks and guarantee lack of starvation. Note however, that fairness of locks does not guarantee fairness of thread scheduling. Thus, one of many threads using a fair lock may obtain it multiple times in succession while other active threads are not progressing and not currently holding the lock. Also note that the untimed tryLock method does not honor the fairness setting. It will succeed if the lock is available even if other threads are waiting.
If you absolutely must wake "consumer" threads in a particular order,* the thing to do would be to give each consumer its own Semaphore, and have each consumer put a reference to its semaphore into a queue before awaiting it.
class MyConsumer {
private final Queue<Semaphore> sleep_q;
private final Semaphore sleep_sem = new Semaphore(0);
public MyConsumer(Queue sleep_q) {
this.sleep_q = sleep_q;
}
private void waitToBeNotified() {
sleep_q.add(sleep_sem);
sleep_sem.acquire();
}
public void whatever() {
doSomeStuff();
waitToBeNotified();
doSomeMoreStuff();
}
The producer can awaken the longest-waiting thread by popping a semaphore from the queue, and releasing a permit to it.
class MyProducer {
private final Queue<Semaphore> sleep_q;
public MyConsumer(Queue sleep_q) {
this.sleep_q = sleep_q;
}
public void goForthAndProduceStuff() {
while (...) {
produceSomething();
awakenAConsumer();
}
}
private void awakenAConsumer() {
Semaphore sem = sleep_q.poll();
if (sem != null) {
sem.release();
}
}
}
* But, see my comment on the original question.

Check size and then perform operation - is it safe for ConcurrentLinkedDeque?

I need to replace the first value in Deque with the new value, only
if the size will exceed the limit. I wrote this code to solve it:
final class Some {
final int buffer;
final Deque<Operation> operations = new ConcurrentLinkedDeque<>();
// constructors ommited;
#Override
public void register(final Operation operation) {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
}
#Override
public void apply() {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
}
}
As you see, I have two methods, that modifies the Deque. I have doubts, that this code will work correctly in the multithreaded environment. The question is: is it safe to check the size() and then performing operations, that modifies the ConcurrentLinkedDeque afterward? I want to have as least locks as possible. So if this code won't work, then I had to introduce locking and then there is no point in the usage of ConcurrentLinkedDeque().
final class Some {
final int buffer;
final Deque<Operation> operations = new LinkedList<>();
final Lock lock = new ReentrantLock();
// constructors ommited;
#Override
public void register(final Operation operation) {
this.lock.lock();
try {
if (this.operations.size() == this.buffer) {
// remove the oldest operation
this.operations.removeFirst();
}
// add new operation to the tail
this.operations.addLast(operation);
} finally {
lock.unlock();
}
}
#Override
public void apply() {
this.lock.lock();
try {
// take the fresh operation from tail and perform it
this.operations.removeLast().perform();
} finally {
this.lock.unlock();
}
}
}
This is the alternative with the Lock. Is that the only way to achieve what I want? I am especially interested in trying to use the concurrent collections.
Concurrent collections are thread-safe when it comes to internal state. In other words, they
Allow multiple threads to read/write concurrently without having to worry that the internal state will become corrupted
Allow iteration and removal while other threads are modifying the collection
Not all, however. I believe CopyOnWriteArrayList's Iterator does not support the remove() operation
Guarantees things such as happens-before
Meaning a write by one thread will happen-before a read by a subsequent thread
However, they are not thread-safe across external method calls. When you call one method it will acquire whatever locks are necessary but those locks are released by the time the method returns. If you're not careful this can lead to a check-then-act race condition. Looking at your code
if (this.operations.size() == this.buffer) {
this.operations.removeFirst();
}
this.operations.addLast(operation);
the following can happen:
Thread-A checks size condition, result is false
Thread-A moves to add new Operation
Before Thread-A can add the Operation, Thread-B checks size condition which results in false as well
Thread-B goes to add new Operation
Thread-A does add new Operation
Oh, no! The Operation added by Thread-A causes the size threshold to be reached
Thread-B, already past the if statement, adds its Operation making the deque have one too many Operations
This is why a check-then-act requires external synchronization, which you do in your second example using a Lock. Note you could also use a synchronized block on the Deque.
Unrelated to your question: You call Operation.perform() in your second example while still holding the Lock. This means no other thread can attempt to add another Operation to the Deque while perform() executes. If this isn't desired you can change the code like so:
Operation op;
lock.lock();
try {
op = deque.pollLast(); // poll won't throw exception if there is no element
} finally {
lock.unlock();
}
if (op != null) {
op.perform();
}
From the doc of size()
BlockquoteBeware that, unlike in most collections, this method is NOT a constant-time operation. Because of the asynchronous nature of these deques, determining the current number of elements requires traversing them all to count them. Additionally, it is possible for the size to change during execution of this method, in which case the returned result will be inaccurate. Thus, this method is typically not very useful in concurrent applications.
While #Slaw is correct, also add that an addition/subtraction can occur during the traversal.
I don't use size() in my software. I keep my own count of what is in the collection with an AtomicInteger. If count.get() < max, I can add. Being a little over max is ok for my usage. You can use a lock on count to force compliance.

How to implement synchronized checks for Bounded Buffer to avoid Race Conditions?

Working with the classic multiple Consumer/Producer problem, and I have an issue that is driving me around the bend, regarding how to avoid race conditions when inserting/removing from a circular buffer. Appreciate any help in advance!
Sample code for circular buffer for example purposes. Similar to my implementation (Note: I cannot use collection types, only arrays for this):
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BoundedBuffer {
private final String[] buffer;
private final int capacity;
private int front;
private int rear;
private int count;
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
public BoundedBuffer(int capacity) {
super();
this.capacity = capacity;
buffer = new String[capacity];
}
public void deposit(String data) throws InterruptedException {
lock.lock();
try {
while (count == capacity) {
notFull.await();
}
buffer[rear] = data;
rear = (rear + 1) % capacity;
count++;
notEmpty.signal();
} finally {
lock.unlock();
}
}
public String fetch() throws InterruptedException {
lock.lock();
try {
while (count == 0) {
notEmpty.await();
}
String result = buffer[front];
front = (front + 1) % capacity;
count--;
notFull.signal();
return result;
} finally {
lock.unlock();
}
}
}
What I need to know is how can I implement a method for checking if the buffer is full/Empty? This method needs to be included in this BoundedBuffer and must be called from another class (Producer/Consumer) before giving the go ahead for/Calling Inserting/Writing methods.
Pseudocode for method in Producer class.
if (!bufferFull) {
buffer.addelement;
}
else {
thread.sleep(5)
threadHasSleptFor++;
}
I am using threads, and there are multiple producers/consumers (In this case 2 producers/consumers, but I may require more). I need it so that if the buffer is full, the thread has to wait until it becomes available for insertion, and the time it waits needs to be stored for output purposes (Not debug, part of the core features). The issue I am having is this:
Thread 1 Producer checks is bufferfull condition, it's false.
Scheduler switches to Thread 2 midway.
Thread 2 also checks bufferfull condition, it's false.
thread 2 proceeds to insert.
Scheduler switches back to Thread 1.
Thread 1 now goes to insert line, as it already checked, but Thread 2 beat it.
Booom.
Somewhat new to Java, though as I understand this is the "time-of-check/time-of-use" race condition issue.
Can someone please advise as to how this can be implemented safely, and how would I loop the code so the threadHasSleptFor variable keeps incrementing on every fail (Providing the methods would be great). I want it so that only the Thread that has requested the check can begin to insert item; the second producer must wait for the lock.
Thanks.
This is by definition impossible to do without higher level locking.
You have to guarantee that the check of whether the buffer is full or not and the following insert are atomic from the thread's perspective which means you have to acquire some common lock to do so. This general problem is indeed called Time of check to time to use and leads to many interesting race conditions down the line.
The solution to these problems is to not check if you can do an operation and then do it, but to just try the operation and handle the error case. So if you don't want to block if the buffer is full with your operation, just implement a tryDeposit method that throws an exception if it can't store a value, or return a boolean success value.
Although in your case if you have to store the time necessary before you could push the value onto the stack, I don't see why a simple:
long start = System.nanotime();
queue.deposit();
long end = System.nanotime();
wouldn't do the trick as well.
If I understand you correctly, you are asking how to make a thread wait until it's OK to call deposit() or wait until it's OK to call fetch(). But, there's no need for that. Your deposit() method will block the calling thread until there is room in the queue, and your fetch() method will block the caller until there is something to fetch. That's what the notFull.await() and notEmpty.await() calls do.
await() unlocks the lock, sleeps until the condition is signalled by another thread, and then it re-locks the lock. The condition may or may not still be true when the caller finally gets the lock again, but that's why you have the await() calls in loops, so that the thread keeps trying until finally it has the lock and the condition is true. Then it does its work (add an item or remove an item), unlocks the lock, and returns.

how to deal with multiple worker threads that may create new work items

I have a queue that contains work items and I want to have multiple threads work in parallel on those items. When a work item is processed it may result in new work items. The problem I have is that I can't find a solution on how to determine if I'm done. The worker looks like that:
public class Worker implements Runnable {
public void run() {
while (true) {
WorkItem item = queue.nextItem();
if (item != null) {
processItem(item);
}
else {
// the queue is empty, but there may still be other workers
// processing items which may result in new work items
// how to determine if the work is completely done?
}
}
}
}
This seems like a pretty simple problem actually but I'm at a loss. What would be the best way to implement that?
thanks
clarification:
The worker threads have to terminate once none of them is processing an item, but as long as at least one of them is still working they have to wait because it may result in new work items.
What about using an ExecutorService which will allow you to wait for all tasks to finish: ExecutorService, how to wait for all tasks to finish
I'd suggest wait/notify calls. In the else case, your worker threads would wait on an object until notified by the queue that there is more work to do. When a worker creates a new item, it adds it to the queue, and the queue calls notify on the object the workers are waiting on. One of them will wake up to consume the new item.
The methods wait, notify, and notifyAll of class Object support an efficient transfer of control from one thread to another. Rather than simply "spinning" (repeatedly locking and unlocking an object to see whether some internal state has changed), which consumes computational effort, a thread can suspend itself using wait until such time as another thread awakens it using notify. This is especially appropriate in situations where threads have a producer-consumer relationship (actively cooperating on a common goal) rather than a mutual exclusion relationship (trying to avoid conflicts while sharing a common resource).
Source: Threads and Locks
I'd look at something higher level than wait/notify. It's very difficult to get right and avoid deadlocks. Have you looked at java.util.concurrent.CompletionService<V>? You could have a simpler manager thread that polls the service and take()s the results, which may or may not contain a new work item.
Using a BlockingQueue containing items to process along with a synchronized set that keeps track of all elements being processed currently:
BlockingQueue<WorkItem> bQueue;
Set<WorkItem> beingProcessed = new Collections.synchronizedSet(new HashMap<WorkItem>());
bQueue.put(workItem);
...
// the following runs over many threads in parallel
while (!(bQueue.isEmpty() && beingProcessed.isEmpty())) {
WorkItem currentItem = bQueue.poll(50L, TimeUnit.MILLISECONDS); // null for empty queue
if (currentItem != null) {
beingProcessed.add(currentItem);
processItem(currentItem); // possibly bQueue.add(newItem) is called from processItem
beingProcessed.remove(currentItem);
}
}
EDIT: as #Hovercraft Full Of Eels suggested, an ExecutorService is probably what you should really use. You can add new tasks as you go along. You can semi-busy wait for termination of all tasks at regular interval with executorService.awaitTermination(time, timeUnits) and kill all your threads after that.
Here's the beginnings of a queue to solve your problem. bascially, you need to track new work and in process work.
public class WorkQueue<T> {
private final List<T> _newWork = new LinkedList<T>();
private int _inProcessWork;
public synchronized void addWork(T work) {
_newWork.add(work);
notifyAll();
}
public synchronized T startWork() throws InterruptedException {
while(_newWork.isEmpty() && (_inProcessWork > 0)) {
wait();
if(!_newWork.isEmpty()) {
_inProcessWork++;
return _newWork.remove(0);
}
}
// everything is done
return null;
}
public synchronized void finishWork() {
_inProcessWork--;
if((_inProcessWork == 0) && _newWork.isEmpty()) {
notifyAll();
}
}
}
your workers will look roughly like:
public class Worker {
private final WorkQueue<T> _queue;
public void run() {
T work = null;
while((work = _queue.startWork()) != null) {
try {
// do work here...
} finally {
_queue.finishWork();
}
}
}
}
the one trick is that you need to add the first work item _before you start any workers (otherwise they will all immediately exit).

How to use java notify correctly in blocking queue implementation

I am trying to understand Java multi-threading constructs, and I am trying to write a simple implementation of blocking queue. Here is the code I have written:
class BlockingBoundedQueue<E>
{
#SuppressWarnings("unchecked")
BlockingBoundedQueue(int size)
{
fSize = size;
fArray = (E[]) new Object[size];
// fBlockingQueue = new ArrayBlockingQueue<E>(size);
}
BlockingQueue<E> fBlockingQueue;
public synchronized void put(E elem)
{
if(fCnt==fSize-1)
{
try
{
// Should I be waiting/locking on the shared array instead ? how ?
wait();
}
catch (InterruptedException e)
{
throw new RuntimeException("Waiting thread was interrupted during put with msg:",e);
}
}
else
{
fArray[fCnt++]=elem;
//How to notify threads waiting during take()
}
}
public synchronized E take()
{
if(fCnt==0)
{
try
{
// Should I be waiting/locking on the shared array instead ? how ?
wait();
}
catch (InterruptedException e)
{
throw new RuntimeException("Waiting thread was interrupted during take with msg:",e);
}
}
return fArray[fCnt--];
//How to notify threads waiting during put()
}
private int fCnt;
private int fSize;
private E[] fArray;
}
I want to notify threads waiting in Take() from put() and vice versa. Can someone please help me with the correct way of doing this.
I checked the java.utils implementation and it uses Condition and ReentrantLocks which are a little complex for me at this stage. I am okay of not being completely robust[but correct] for the sake of simplicity for now.
Thanks !
The short answer is, call notifyAll() where you have the comments //How to notify threads waiting during take()
Now for the more complete answer...
The reference to read is : Java Concurrency in Practice. The answer to your question is in there.
However, to briefly answer your question: in Java, threads synchronize by locking on the same object and using wait() and notify() to safely change state. The typical simplified flow is:
Thread A obtains a lock by entering a synchronized block on a lock object
Thread A checks some condition in a loop, if not "OK to go" call thread.wait(), which is a blocking call that "releases" the lock so other code synchronized on the same lock object can proceed
Thread B obtains the same lock and may do something that changes the condition thread A is waiting for. When it calls notifyAll(), thread A will wake up and recheck the condition and (may) proceed
Some things to remember about synchronization are:
it is about keeping state of objects consistent by making changes to state atomic. "Atomic" means the entire change (e.g. to multiple fields) is guaranteed to complete (no partial, and therefore inconsistent, changes)
it is cooperative - code synchronized on a given lock object has in common the state that is being changed and the conditions that allow that state change - you wait and notify about the same "subject". Each part of state should be guarded by its own lock object - usually a private field, e.g. private Object lock = new Object(); would be fine
methods that are synchronized use this as the lock object - doing this is easy but potentially expensive, because you are locking for every call, instead of just when you need to
static methods that are synchronized use the Class object as the lock object

Categories