Java multithreading - awaiting condition and releasing all threads - java

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();
}
}

Related

Java locking simple multi threaded queue class to avoid starvation

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.

How can I make a Java thread do a different task rather than block if a semaphore lock acquire/tryAcquire fails?

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.

Unsafe.park vs Object.wait

I have a couple of questions regarding Unsafe.park and Object.wait (and their corresponding resume methods):
Which one should be used in general?
Which one has better performance?
Is there any advantage to using Unsafe.park over Object.wait?
Most efficient wait is LockSupport.park/unpark, which doesn't require nasty (direct) usage of Unsafe, and doesn't pay to resynchronize your thread's local cache of memory.
This point is important; the less work you do, the more efficient. By not synchronizing on anything, you don't pay to have your thread check with main memory for updates from other threads.
In most cases, this is NOT what you want. In most cases, you want your thread to see all updates that happened "before now", which is why you should use Object.wait() and .notify(), as you must synchronize memory state to use them.
LockSupport allows you to safely park a thread for a given time, and so long as no other thread tries to unpark you, it will wait for that long (barring spurious wake ups). If you need to wait for a specific amount of time, you need to recheck the deadline and loop back into park() until that time has actually elapsed.
You can use it to "sleep" efficiently, without another thread to have to wake you up via LockSupport.parkNanos or .parkUntil (for millis; both methods just call Unsafe for you).
If you do want other threads to wake you up, chances are high that you need memory synchronization, and should not use park (unless carefully orchestrating volatile fields without race conditions is your thing).
Good luck, and happy coding!
You're not supposed to use either of these methods if you're an application programmer.
They are both too low level, easy to screw up and not meant to be used outside libraries.
Why not try to use a higher level construct like java.util.concurrent.locks ?
To answer your question. park(...) works directly on the thread. It takes the thread as a parameter and puts it to sleep until unpark is called on the thread, unless unpark has already been called.
It's supposed to be faster than Object.wait(), which operates on the monitor abstraction if you know which thread you need to block/unblock.
Btw unpark is not really that Unsafe if used from inside Java:
public native void unpark(Object thread)
Unblock the given thread
blocked on park, or, if it is not blocked, cause the subsequent call
to park not to block. Note: this operation is "unsafe" solely because
the caller must somehow ensure that the thread has not been destroyed.
Nothing special is usually required to ensure this when called from
Java (in which there will ordinarily be a live reference to the
thread) but this is not nearly-automatically so when calling from
native code.
LockSupport.park/unpark has better performance, but it's too low level API.
Besides, they have some different operations maybe you should notice:
Object lockObject = new Object();
Runnable task1 = () -> {
synchronized (lockObject) {
System.out.println("thread 1 blocked");
try {
lockObject.wait();
System.out.println("thread 1 resumed");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
Thread thread1 = new Thread(task1);
thread1.start();
Runnable task2 = () -> {
System.out.println("thread 2 running ");
synchronized (lockObject) {
System.out.println("thread 2 get lock");
lockObject.notify();
}
};
Thread thread2 = new Thread(task2);
thread2.start();
In this case, thread2 can get lock and notify the thread1 to resumed, because lockObject.wait(); will release the lock.
Object lockObject = new Object();
Runnable task1 = () -> {
synchronized (lockObject) {
System.out.println("thread 1 blocked");
LockSupport.park();
System.out.println("thread 1 resumed");
}
};
Thread thread1 = new Thread(task1);
thread1.start();
Runnable task2 = () -> {
System.out.println("thread 2 running ");
synchronized (lockObject) {
System.out.println("thread 2 get lock");
LockSupport.unpark(thread1);
}
};
Thread thread2 = new Thread(task2);
thread2.start();
However, if you use LockSupport.park/unpark like this, it will cause dead lock. because thread1 won't release the lock by using LockSupport.park. therefore, thread1 can't resumed.
So be careful, they have different behaviors besides blocking the thread. And in fact, there are some Class we can use it conveniently to coordinate in multi-thread environment, such as CountDownLatch, Semaphore, ReentrantLock
If you're managing concurrency with synchronized blocks, then you would use Object.wait, notify, and notifyAll for signalling. This is the first kind of concurrency control that Java supported, and it was considered to be very easy to use at the time. It certainly was, compared to everything else that was around.
These days, though, there are lots of classes in java.util.concurrent don't require as much specialized knowledge to work with. These are the things that should be used by average programmers these days.
The park* and unpark methods in LockSupport are what you would use if you are writing your own lock-free algorithms and data structures. They are high-performance constructs that don't require locks to work with, and they are very well designed to make this kind of work as easy as it can be... but that is still very difficult and tricky work that is best left to experts.

Is it possible for threads not sharing a common resource to notify based on thread-id/name?

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.

How to pause thread in java?

So what's the best way to pause a thread? So far I have something like this: In main loop of the thread, first line is:
while (paused == true) {
Thread.sleep(refreshRate);
}
And it works perfercly. I can change paused state pressing P key. But Im looking for better, more professional solution. I know about reentrant locks and conditions. So I could use them on the thread. And then presing P would release singalAll() method. But it would slow my app a lot because of synchronization which I don't really need in this thread. So what is the best, most perform way to solve it? Maybe using synchronization blocks?
synchronized (new Object()) {
}
Then just part of code would be synchronized. Or maybe I should use semaphores?
You should use a wait/notify scheme such as:
Create an atomic boolean flag in the thread to be paused.
When the flag is set the thread should call wait() on a lock object
When you want to unpause the thread reset the flag and call notify() on the lock object
Use a PauseableThread like the one I posted a while ago in answer to a question much like yours.
It uses ReadWriteLocks to implement so you don't have the overhead of synchronization.
Use wait() and notify()
Object waitLock = new Object();
//...
// waiter Thread
synchronized (waitLock) {
waitLock.wait();
}
// wake up with
waitLock.notify();

Categories