I'm currently reviewing concurrency and wanted to double check my understanding.
Let's say I have a simple queue class that I want to use multiple threads to take jobs off of the queue and run.
class JobQueue {
static Queue<Job> jobq;
ExecutorService exec;
public void addJob(Job j)
synchronized(jobq) {
jobq.add(j)
}
public void runJob() {
synchronized(jobq) {
while (!jobq.isEmpty()) {
exec.submit(() -> jobq.poll().run());
}
}
}
Pardon my syntax I quickly put this together. Anyways, I have a 2 part question.
To avoid starvation of the addJob method, would it be better to lock the !jobq.isEmpty() and then unlock, and then separately lock the exec.submit...? That way in between checking the jobq is empty and polling a job off, the addJob has a chance to acquire the lock?
If the above is the case (it's better to unlock after the while check), how would you do so with this synchronized object? Since the exec.submit is nested within the while loop which is nested within the synchronized(jobq) loop.
To avoid starvation of the addJob method, would it be better to lock the !jobq.isEmpty() and then unlock, and then separately lock the exec.submit...? That way in between checking the jobq is empty and polling a job off, the addJob has a chance to acquire the lock?
In this case locking the whole while{...} loop is OK because exec.submit... doesn't do much: it actually only creates and returns a Future, while the task is executed in another thread.
Also if !jobq.isEmpty() and exec.submit... were locked separately, then you would get an additional problem: what if in between these locks another thread executes runJob() and jobq becomes empty.
Related
I've been learning concurrency in java and was looking at java semaphores and ran into a problem. I have multiple threads trying to acquire one of multiple locks to access a critical section protected by a semaphore and want my all threads who have failed to acquire the lock to do a specific task and then attempt to reacquire the lock. Every time the acquisition fails I want the thread to do the waiting task I have made and when it's done try again. repeat until acquired. Looking at the java docs for the java semaphore class, all the acquire methods seem to do some form of blocking one way or another. How can I accomplish what I want?
Use tryAcquire:
while(!done) {
if(sem.tryAcquire()) {
// semaphore acquired
done=true
} else {
// Semaphore not acquired, do something else
}
}
There is another variant of tryAcquire with a timeout and you can use that if you want to wait a while and then continue.
I have the following piece of code:
public static void main(String[] args) {
...
while(condition.continueListening()) {
}
log.info("Finished");
}
The condition object creates its own thread that after one condition is met, make the method continueListening, to return false.
The thing is that, I want the main thread to not to finish until that method returns false, and the way I implemented it, it's by using this structure that it's quite "hard" for the CPU, do you know any other approach that could work better?
What is continueListening checking? If its just a random piece of state, you don't really have a good choice, best you can do is make your thread sleep for a little bit, say a half second in the while loop.
But if you can change continueListening, then you can have it block until an event happens and it should continue. Java has many options for this, some could be:
You could wait for the other thread to exit using Thread.join().
Wait for the thread to notify on some object that it has done something (similar idea to join but the thread can carry on and do something else). Object.wait(), Object.notify().
Use the Java "executor", this is similar to waiting for a thread to exit, but has built in means to transfer results and errors, and allows Java to use things like thread pools. See ExecutorService and Future.get()
Various other waitable event objects or queues. Such as doing something manually with Future and Promise, or BlockingQueue.
If I know the ID of the thread I wish to notify, and share no other common resource, can I notify it?
Both the threads have been initiated by the same application.
the other thread went into wait by using Thread.currentThread().wait(500);
Yes - but you must stop using wait.
The technique is to maintain a Map<String,BlockingQueue> containing a queue for each thread that is running. The String key is the thread ID.
When you want the thread to pause, use queue.poll(long, TimeUnit) instead of wait. You merely need to put something in the queue to wake up the thread and obviously if you know the ID of the thread you can easily obtain it's Queue from the Map.
As long as it's in the same ThreadGroup, you can iterate through all the threads using Thread.enumerate() and find the given thread by it's id and do the usual synchronize and .notify().
This provides additional ways of iterating over all the Threads.
You would want to notify only threads waiting on the same lock. Don't use current thread object as the lock, it doesn't help. Once a thread has been awakened you need to check against a condition to guard against spurious wake ups. if you are sure that there is only one thread waiting on the lock then calling notify on the lock object should wake up the waiting thread.
You can give the threads some common object on which to communicate, and so you won't have to rely on thread names.
Example:
class Notifier extends Thread {
private final Object common;
Notifier(Object common) { this.common = common; }
public void run() {
// do work
synchronized (common) { common.notify(); }
}
}
class Waiter extends Thread {
private final Object common;
Waiter(Object common) { this.common = common; }
public void run() {
// do work
synchronized (common) { common.wait(TIMEOUT); }
}
}
A better yet approach would be to use a java.util.concurrent.CountDownLatch for the same effect.
Yes it is possible. But it is ugly and potentially fragile and/or inefficient.
As #nos says you can use Thread.enumerate() to enumerate the Thread objects in your ThreadGroup, test each one until you can find the thread with the expected name and/or thread id. That is clearly inefficient if there are lots of threads in the group.
The fragility arises in the following respects:
The thread with a given name or id may no longer exist.
There could be multiple threads with the same name.
Thread id values will eventually be recycled when enough threads have been and gone.
and on the synchronization side,
There could conceivably be other parts of your application (or library code) that synchronize using wait/notify on the Thread objects, and you could get unwanted notifies as a result.
On some Java platforms, (at least historically) it is possible to get spontaneous notifications ... so using wait / notify without testing a shared condition variable might result in bad synchronization.
IMO, you would be better off creating (private) objects that you can wait/notify on, and using proper condition variables. Or it that is unappealing, use one of the existing higher level concurrency class for synchronizing.
I have a relatively simple issue to solve, namely I would like to make all threads await a certain condition to happen and then proceed. It can be explained by the code below:
void doSth(){ //shared by multiple threads
...
if(!conditionMet())
await();
//procceed further
resetCondition()
}
I do not want to use locking and conditions, as it seems unnecessary. CountDownLatch would be perfect, but I have to reset the latch, and CyclicBarrier would not work either because I have no idea how many threads need to call await. Also, when the signal is sent to awaiting threads, they should all be released and proceed. How would you guys approach this?
I recommend Phaser
I have no idea how many threads need to call await.
For each thread that eventually needs to wait, invoke phaser.register() [register doesn't wait, it tells the phaser to expect another thread to either wait or to trip the barrier]
CountDownLatch would be perfect, but I have to reset the latch
Once a thread completes, invoke phaser.arriveAndAwaitAdvance(). At that point, all threads will wait there until the number of threads registered == number of threads arrived.
I do not want to use locking and conditions, as it seems unnecessary.
Why? This smacks of premature optimization to me. If you don't know how many threads there are then you can't use CountDownLatch. This seems to me to be a perfect use case of standard locks and conditions. The only time we worry about their use is when we are trying hard not to get threads to block. But in this case blocking is exactly what you want.
I don't really see why you wouldn't want to use locks? Any "barrier" mechanism will internally use some form of synchronization, so there's no real "unleash all threads at the same time" solution.
Best I can come up with:
private final Object lock = new Object();
void doSth() { //shared by multiple threads
...
synchronized(lock) {
while(!conditionMet()) {
lock.wait();
}
}
}
void release() {
synchronized(lock) {
resetCondition();
lock.notifyAll();
}
}
Someone at work just asked for the reasoning behind having to wrap a wait inside a synchronized.
Honestly I can't see the reasoning. I understand what the javadocs say--that the thread needs to be the owner of the object's monitor, but why? What problems does it prevent? (And if it's actually necessary, why can't the wait method get the monitor itself?)
I'm looking for a fairly in-depth why or maybe a reference to an article. I couldn't find one in a quick google.
Oh, also, how does thread.sleep compare?
edit: Great set of answers--I really wish I could select more than one because they all helped me understand what was going on.
Lots of good answers here already. But just want to mention here that the other MUST DO when using wait() is to do it in a loop dependent on the condition you are waiting for in case you are seeing spurious wakeups, which in my experience do happen.
To wait for some other thread to change a condition to true and notify:
synchronized(o) {
while(! checkCondition()) {
o.wait();
}
}
Of course, these days, I'd recommend just using the new Condition object as it is clearer and has more features (like allowing multiple conditions per lock, being able to check wait queue length, more flexible schedule/interrupt, etc).
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
lock.lock();
try {
while (! checkCondition()) {
condition.await();
}
} finally {
lock.unlock();
}
}
If the object does not own the object monitor when it calls Object.wait(), it will not be able to access the object to setup a notify listener until the the monitor is released. Instead, it will be treated as a thread attempting to access a method on a synchronized object.
Or to put it another way, there is no difference between:
public void doStuffOnThisObject()
and the following method:
public void wait()
Both methods will be blocked until the object monitor is released. This is a feature in Java to prevent the state of an object from being updated by more than one thread. It simply has unintended consequences on the wait() method.
Presumably, the wait() method is not synchronized because that could create situations where the Thread has multiple locks on the object. (See Java Language Specifications/Locking for more info on this.) Multiple locks are a problem because the wait() method will only undo one lock. If the method were synchronized, it would guarantee that only the method's lock would be undone while still leaving a potential outer lock undone. This would create a deadlock condition in the code.
To answer your question on Thread.sleep(), Thread.sleep() does not guarantee that whatever condition you are waiting on has been met. Using Object.wait() and Object.notify() allows a programmer to manually implement blocking. The threads will unblock once a notify is sent that a condition has been met. e.g. A read from disk has finished and data can be processed by the thread. Thread.sleep() would require the programmer to poll if the condition has been met, then fall back to sleep if it has not.
It needs to own the monitor, since the purpose of the wait() is to release the monitor and let other threads obtain the monitor to do processing of their own. The purpose of these methods (wait/notify) is to coordinate access to synchronized code blocks between two threads that require each other to perform some functionality. It is not simply a matter of making sure access to a data structure is threadsafe, but to coordinate events between multiple threads.
A classic example would be a producer/consumer case where one thread pushes data to a queue, and another thread consumes the data. The consuming thread would always require the monitor to access the queue, but would release the monitor once the queue is empty. The producer thread would then only get access to write to the thread when the consumer is no longer processing. It would notify the consumer thread once it has pushed more data into the queue, so it can regain the monitor and access the queue again.
Wait gives up the monitor, so you must have it to give it up. Notify must have the monitor as well.
The main reason why you want to do this is to ensure that you have the monitor when you come back from wait() -- typically, you are using the wait/notify protocol to protect some shared resource and you want it to be safe to touch it when wait returns. The same with notify -- usually you are changing something and then calling notify() -- you want to have the monitor, make changes, and call notify().
If you made a function like this:
public void synchWait() {
syncronized { wait(); }
}
You would not have the monitor when wait returned -- you could get it, but you might not get it next.
Here's my understanding on why the restriction is actually a requirement. I'm basing this on a C++ monitor implementation I made a while back by combining a mutex and a condition variable.
In a mutex+condition_variable=monitor system, the wait call sets the condition variable into a wait state and releases the mutex. The condition variable is shared state, so it needs to be locked to avoid race conditions between threads that want to wait and threads that want to notify. Instead of introducing yet another mutex to lock its state, the existing mutex is used. In Java, the mutex is correctly locked when the about-to-wait thread owns the monitor.
Mostly wait is done if there is a condition say a queue is empty.
If(queue is empty)
queue.wait();
Let us assume the queue is empty.
In case if the current thread pre-empts after checking the queue, then if another
thread adds few elements to queue, the current thread will not know and will go for wait
state. Thats wrong.
So we should have something like
Synchornized(queue)
{
if(queue is empty)
queue.wait();
}
Now let us consider what if they made wait itself as synchronized. As already mentioned in one of the comments, it releases only one lock. That means if wait() was synchronized in the above code only one lock would have been released. Implies that current thread will go for wait with the lock for the queue.