Thread.sleep() vs Thread.onSpinWait - java

I have a spin-wait loop that is busy-waiting for a flag to be set. However, it can take a lot of time for that to happen - minutes, or even hours.
Would Thread.sleep() be more efficient than Thread.onSpinWait​()?

From the documentation of Thread#onSpinWait:
The runtime may take action to improve the performance of invoking spin-wait loop constructions.
Thread#sleep does not do this, but rather releases the processor to another runnable thread until its sleep time has elapsed.
If I were you, I would redesign your system to use interrupts (events) rather than polling (busy waiting), as that would result in a better performance boost than either Thread#sleep or Thread#onSpinWait.

So you wanted to see a short example about Object and its long-available wait() and notify/All() methods? (They are already there in JLS 1.0, from 20+ years ago)
Say no more:
public class NotifyTest {
private boolean flag = false;
public synchronized boolean getFlag() {
return flag;
}
public synchronized void setFlag(boolean newFlag) {
flag = newFlag;
notifyAll();
}
public static void main(String[] args) throws Exception {
final NotifyTest test = new NotifyTest();
new Thread(new Runnable() {
#Override
public void run() {
System.out.printf("I am thread at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
synchronized (test) {
try {
test.wait();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
System.out.printf("I am thread at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
}
}).start();
System.out.printf("I am main at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
Thread.sleep(2000);
test.setFlag(true);
System.out.printf("I am main at %,d, flag is %b\n",
System.currentTimeMillis(), test.getFlag());
}
}
If your wait loop has anything else to do, Object.wait() has variants with timeout too.
So objects can be wait()-ed on and then waiting threads can be notified (one of the waiters via notify() or all of them via notifyAll()), and they do not even have to know about each other.
As both waiting and notifying has to happen inside a synchronized block, it is safe and possible to start the block, check the variable/flag/anything, and issue the wait conditionally (just these constructs are not shown here).

Neither sleep nor a spin lock is what you want in this situation. sleep is the wrong choice because you don't know how long you're going to need to sleep beforehand. Doing some sort of spin lock loop is wrong because spin locks are busy waits and thus consume CPU cycles and are only really meant for very short waits in anticipation of a resource becoming available very quickly. What you want to do here is set up a semaphore. Have thread 1 wait for the semaphore to be set by thread 2.

Related

Java: two WAITING + one BLOCKED threads, notify() leads to a livelock, notifyAll() doesn't, why?

I was trying to implement something similar to Java's bounded BlockingQueue interface using Java synchronization "primitives" (synchronized, wait(), notify()) when I stumbled upon some behavior I don't understand.
I create a queue capable of storing 1 element, create two threads that wait to fetch a value from the queue, start them, then try to put two values into the queue in a synchronized block in the main thread. Most of the time it works, but sometimes the two threads waiting for a value start seemingly waking up each other and not letting the main thread enter the synchronized block.
Here's my (simplified) code:
import java.util.LinkedList;
import java.util.Queue;
public class LivelockDemo {
private static final int MANY_RUNS = 10000;
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < MANY_RUNS; i++) { // to increase the probability
final MyBoundedBlockingQueue ctr = new MyBoundedBlockingQueue(1);
Thread t1 = createObserver(ctr, i + ":1");
Thread t2 = createObserver(ctr, i + ":2");
t1.start();
t2.start();
System.out.println(i + ":0 ready to enter synchronized block");
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
t1.join();
t2.join();
System.out.println();
}
}
public static class MyBoundedBlockingQueue {
private Queue<Object> lst = new LinkedList<Object>();;
private int limit;
private MyBoundedBlockingQueue(int limit) {
this.limit = limit;
}
public synchronized void addWhenHasSpace(Object obj) throws InterruptedException {
boolean printed = false;
while (lst.size() >= limit) {
printed = __heartbeat(':', printed);
notify();
wait();
}
lst.offer(obj);
notify();
}
// waits until something has been set and then returns it
public synchronized Object getWhenNotEmpty() throws InterruptedException {
boolean printed = false;
while (lst.isEmpty()) {
printed = __heartbeat('.', printed); // show progress
notify();
wait();
}
Object result = lst.poll();
notify();
return result;
}
// just to show progress of waiting threads in a reasonable manner
private static boolean __heartbeat(char c, boolean printed) {
long now = System.currentTimeMillis();
if (now % 1000 == 0) {
System.out.print(c);
printed = true;
} else if (printed) {
System.out.println();
printed = false;
}
return printed;
}
}
private static Thread createObserver(final MyBoundedBlockingQueue ctr,
final String name) {
return new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println(name + ": saw " + ctr.getWhenNotEmpty());
} catch (InterruptedException e) {
e.printStackTrace(System.err);
}
}
}, name);
}
}
Here's what I see when it "blocks":
(skipped a lot)
85:0 ready to enter synchronized block
85:0 entered synchronized block
85:2: saw hello
85:1: saw world
86:0 ready to enter synchronized block
86:0 entered synchronized block
86:2: saw hello
86:1: saw world
87:0 ready to enter synchronized block
............................................
..........................................................................
..................................................................................
(goes "forever")
However, if I change the notify() calls inside the while(...) loops of addWhenHasSpace and getWhenNotEmpty methods to notifyAll(), it "always" passes.
My question is this: why does the behavior vary between notify() and notifyAll() methods in this case, and also why is the behavior of notify() the way it is?
I would expect both methods to behave in the same way in this case (two threads WAITING, one BLOCKED), because:
it seems to me that in this case notifyAll() would only wake up the other thread, same as notify();
it looks like the choice of the method which wakes up a thread affects how the thread that is woken up (and becomes RUNNABLE I guess) and the main thread (that has been BLOCKED) later compete for the lock — not something I would expect from the javadoc as well as searching the internet on the topic.
Or maybe I'm doing something wrong altogether?
Without looking too deeply into your code, I can see that you are using a single condition variable to implement a queue with one producer and more than one consumer. That's a recipe for trouble: If there's only one condition variable, then when a consumer calls notify(), there's no way of knowing whether it will wake the producer or wake the other consumer.
There are two ways out of that trap: The simplest is to always use notifyAll().
The other way is to stop using synchronized, wait(), and notify(), and instead use the facilities in java.util.concurrent.locks.
A single ReentrantLock object can give you two (or more) condition variables. Use one exclusively for the producer to notify the consumers, and use the other exclusively for the consumers to notify the producer.
Note: The names change when you switch to using ReentrantLocks: o.wait() becomes c.await(), and o.notify() becomes c.signal().
There appears to be some kind of fairness/barging going on using intrinsic locking - probably due to some optimization. I am guessing, that the native code checks to see if the current thread has notified the monitor it is about to wait on and allows it to win.
Replace the synchronized with ReentrantLock and it should work as you expect it. The different here is how the ReentrantLock handles waiters of a lock it has notified on.
Update:
Interesting find here. What you are seeing is a race between the main thread entering
synchronized (ctr) {
System.out.println(i + ":0 entered synchronized block");
ctr.addWhenHasSpace("hello");
ctr.addWhenHasSpace("world");
}
while the other two thread enter their respective synchronized regions. If the main thread does not get into its sync region before at least one of the two, you will experience this live-lock output you are describing.
What appears to be happening is that if both the two consumer threads hit the sync block first they will ping-pong with each other for notify and wait. It may be the case the JVM gives threads that are waiting priority to the monitor while threads are blocked.

how to synchronize a set of multiple threads with respect to a single thread in Java

Suppose that I have an arraylist called myList of threads all of which are created with an instance of the class myRunnable implementing the Runnable interface, that is, all the threads share the same code to execute in the run() method of myRunnable. Now suppose that I have another single thread called singleThread that is created with an instance of the class otherRunnable implementing the Runnable interface.
The synchornization challenge I have to resolve for these threads is the following: I need all of the threads in myList to execute their code until certain point. Once reached this point, they shoud sleep. Once all and only all of the threads in myList are sleeping, then singleThread should be awakened (singleThread was already asleep). Then singleThread execute its own stuff, and when it is done, it should sleep and all the threads in myList should be awakened. Imagine that the codes are wrapped in while(true)'s, so this process must happen again and again.
Here is an example of the situation I've just described including an attempt of solving the synchronization problem:
class myRunnable extends Runnable
{
public static final Object lock = new Object();
static int count = 0;
#override
run()
{
while(true)
{
//do stuff
barrier();
//do stuff
}
}
void barrier()
{
try {
synchronized(lock) {
count++;
if (count == Program.myList.size()) {
count = 0;
synchronized(otherRunnable.lock) {
otherRunnable.lock.notify();
}
}
lock.wait();
}
} catch (InterruptedException ex) {}
}
}
class otherRunnable extend Runnable
{
public static final Object lock = new Object();
#override
run()
{
while(true)
{
try {
synchronized(lock) {
lock.wait();
} catch (InterruptedException ex) {}
// do stuff
try {
synchronized(myRunnable.lock) {
myRunnable.notifyAll();
}
}
}
}
class Program
{
public static ArrayList<Thread> myList;
public static void main (string[] args)
{
myList = new ArrayList<Thread>();
for(int i = 0; i < 10; i++)
{
myList.add(new Thread(new myRunnable()));
myList.get(i).start();
}
new Thread(new OtherRunnable()).start();
}
}
Basically my idea is to use a counter to make sure that threads in myList just wait except the last thread incrementing the counter, which resets the counter to 0, wakes up singleThread by notifying to its lock, and then this last thread goes to sleep as well by waiting to myRunnable.lock. In a more abstract level, my approach is to use some sort of barrier for threads in myList to stop their execution in a critical point, then the last thread hitting the barrier wakes up singleThread and goes to sleep as well, then singleThread makes its stuff and when finished, it wakes up all the threads in the barrier so they can continue again.
My problem is that there is a flaw in my logic (probably there are more). When the last thread hitting the barrier notifies otherRunnable.lock, there is a chance that an immediate context switch could occur, giving the cpu to singleThread, before the last thread could execute its wait on myRunnable.lock (and going to sleep). Then singleThread would execute all its stuff, would execute notifyAll on myRunnable.lock, and all the threads in myList would be awakened except the last thread hitting the barrier because it has not yet executed its wait command. Then, all those threads would do their stuff again and would hit the barrier again, but the count would never be equal to myList.size() because the last thread mentioned earlier would be eventually scheduled again and would execute wait. singleThread in turn would also execute wait in its first line, and as a result we have a deadlock, with everybody sleeping.
So my question is: what would be a good way to synchronize these threads in order to achieve the desired behaviour described before but at the same time in a way safe of deadlocks??
Based on your comment, sounds like a CyclicBarrier would fit your need exactly. From the docs (emphasis mine):
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
Unfortunately, I haven't used them myself, so I can't give you specific pointers on them. I think the basic idea is you construct your barrier using the two-argument constructor with the barrierAction. Have your n threads await() on this barrier after this task is done, after which barrierAction is executed, after which the n threads will continue.
From the javadoc for CyclicBarrier#await():
If the current thread is the last thread to arrive, and a non-null barrier action was supplied in the constructor, then the current thread runs the action before allowing the other threads to continue. If an exception occurs during the barrier action then that exception will be propagated in the current thread and the barrier is placed in the broken state.

Are wait() and notify() unreliable despite of synchronized?

I recently discovered that using synchronized won't prevent any dead locks.
E.g. within this code:
ArrayList <Job> task;
...
public void do(Job job){
synchronized(tasks){
tasks.add(job);
}
synchronized(this){
notify();
}
}
public void run(){
while(true){
for (int = 0;i<tasks.size();i++){
synchronized(tasks){
Job job = tasks.get(i);
}
//do some job here...
}
synchronized(this){
wait(); //lock will be lost...
notifier = false; //lock will be acquired again after notify()
}
}
}
Now, what is the problem? Well, if the running thread isn't waiting, he won't see any notifications (i.e. notify() calls), therefore he may run into a dead lock and not handle the tasks he received! (Or he may handle them too late...)
Therefore I implemented this code:
private volatile boolean notifier = false;
ArrayList <Job> task;
...
public void do(Job job){
synchronized(tasks){
tasks.add(job);
}
synchronized(this){
notifier = true;
notify();
}
}
public void run(){
while(true){
for (int = 0;i<tasks.size();i++){
synchronized(tasks){
Job job = tasks.get(i);
}
//do some job here...
}
synchronized(this){
if(!notifier){
wait(); //lock will be lost...
notifier = false; //lock will be acquired again after notify()
}
}
}
}
Is this correct or am I missing something? And can it be done easier?
Now, what is the problem? Well, if the running thread isn't waiting, he won't see any notifications (i.e. notify() calls), therefore he may run into a dead lock and not handle the tasks he received!
Right. This is not a case of being "unreliable" but rather a case of language definition. The notify() call does not queue up notifications. If no threads are waiting then the notify() will effectively do nothing.
can it be done easier?
Yes. I'd look into using BlockingQueue -- a LinkedBlockingQueue should work well for you. One thread call pull from the queue and the other can add to it. It will take care of the locking and signaling for you. You should be be able to remove a large portion of your hand written code once you start using it.
I was tricked by your question at first.
Your synchronize(this) on thread object don't make sense. I in the past also do this stuff to make wait() not throwing compilation error.
Only synchronize(tasks) make sense as you are waiting and want to acquire this resources.
Having a for loop, it is bad design. In the consumer-producer problem. get a job at the same time remove a job. better fetch a job once at a time.
public void do(Job job){
synchronized(tasks){
tasks.add(job);
notify();
}
}
public void run(){
Job job;
while(true){
//This loop will fetch the task or wait for task notification and fetch again.
while (true){
synchronized(tasks){
if(tasks.size()>0){
job = tasks.getTask(0);
break;
}
else
wait();
}
}
//do some job here...
}
}
The result actually isn't a dead lock, but rather a starvation of the task/job itself. Because no threads are "locked", the task just won't be done until another thread calls do(Job job).
Your code is almost correct - beside the missing exception handling when calling wait() and notify(). But you may put the task.size() within a synchronisation block, and you may block the tasks during the hole process because a deletion of a job within tasks by another thread would let the loop to fail:
...
while(true){
synchronized(tasks){
for (int = 0;i<tasks.size();i++){ //could be done without synchronisation
Job job = tasks.get(i); //if noone deletes any tasks
}
//do some job here...
}
...
Just note that your code is blocking. Non-blocking might be faster and look like this:
ArrayList <Job> tasks;
...
public void do(Job job){
synchronized(tasks){
tasks.add(job);
}
}
public void run(){
while(true){
int length;
synchronized(tasks){
length = tasks.size();
}
for (int = 0;i<length;i++){
Job job = tasks.get(i); //can be done without synchronisation if noone deletes any tasks...otherwise it must be within a synchronized block
//do some job here...
}
wait(1); //wait is necessary and time can be set higher but never 0!
}
}
What can we learn? Well, within non-blocking threads no notify(), wait() and synchronized are needed. And setting wait(1) doesn't even use more CPU when idle (don't set wait(0) because this would be treated as wait().
However, be careful because using wait(1) may be slower than using wait() and notify(): Is wait(1) in a non-blocking while(true)-loop more efficient than using wait() and notify()? (In other words: Non-blocking might be slower than blocking!)

How does wait and notify work?

I need to know how wait() and notify() works exactly? I couldn't achieve its working by using wait() and notify() as such. Instead if I use a while() loop for wait, it works properly. How is it so? Why can't I use just wait() and notify() simply?
have you read the documentation of the wait-notify functions ?
anyway, for the best way to achieve a wait-notify mechanism, use something like this (based on this website) :
public class WaitNotifier {
private final Object monitoredObject = new Object();
private boolean wasSignalled = false;
/**
* waits till another thread has called doNotify (or if this thread was interrupted), or don't if was already
* notified before
*/
public void doWait() {
synchronized (monitoredObject) {
while (!wasSignalled) {
try {
monitoredObject.wait();
} catch (final InterruptedException e) {
break;
}
}
wasSignalled = false;
}
}
/**
* notifies the waiting thread . will notify it even if it's not waiting yet
*/
public void doNotify() {
synchronized (monitoredObject) {
wasSignalled = true;
monitoredObject.notify();
}
}
}
do note, that each instance of this class should be used only once, so you might want to change it if you need to use it multiple times.
wait() and notify() are used in synchronized block while using threads to suspend and resume where left off.
Wait immediately looses the lock, whereas Nofity will leave the lock only when the ending bracket is encountered.
You can also refer this sample example:
public class MyThread implements Runnable {
public synchronized void waitTest() {
System.out.println("Before Wait");
wait();
System.out.println("After Wait");
}
public synchronized void notifyTest() {
System.out.println("Before Notify");
notify();
System.out.println("After Notify");
}
}
public class Test {
public static void main(String[] args) {
Thread t = new Thread(new MyThread());
t.start();
}
}
I think you are asking why does it work with while loop and does not without.
The answer is when your program calls wait() the operation system suspends your thread and activates (starts) another, and there will happen so called context switch.When OS suspend a thread it needs to save some "meta data" about your thread in order to be able to resume that thread later, PC register is what will answer your question.Basically PC (Program Counter) is a pointer to next instruction which the thread should do or is going to do, after being resumed a thread uses it to understand which instruction it was going to do when OS suspended him, and continues by that instruction (in this case, if you want to look at it by the means of Java program, the next instruction will be the next line after call to wait()).As written in "Java Concurrency in Practice"
Every call to wait is implicitly associated with a specific condition predicate. When calling wait regarding a particular
condition predicate, the caller must already hold the lock associated with the condition queue, and that lock must also
guard the state variables from which the condition predicate is composed.
Because your thread waits because some condition was not met (it should be) after returning to the method that it was suspended in, it needs to recheck that condition to see is it met yet.If condition is met it will not wait anymore, if it's not met it will call wait() again ( as it is in while loop).The important thing to know here is
PC (Program Counter) concept
and
The fact that a Thread that calls wait() on your method will not exit the method -> wait -> get resumed again -> call the method again, instead it will wait -> get resumed again -> continue from the point (instruction/line) where it was suspended (called wait())

Synchronized blocks and Locks

I have two threads and I am currently doing locking using an Object's notify() and wait() methods inside Synchronized blocks. I wanted to make sure that the main thread is never blocked so I used a boolean this way (only relevant code provided.)
//Just to explain an example queue
private Queue<CustomClass> queue = new Queue();
//this is the BOOLEAN
private boolean isRunning = false;
private Object lock;
public void doTask(){
ExecutorService service = Executors.newCachedThreadPool();
//the invocation of the second thread!!
service.execute(new Runnable() {
#Override
public void run() {
while(true){
if (queue.isEmpty()){
synchronized (lock){
isRunning = false; //usage of boolean
lock.wait();
}
}
else{
process(queue.remove());
}
}
});
}
//will be called from a single thread but multiple times.
public void addToQueue(CustomClass custObj){
queue.add(custObj);
//I don't want blocking here!!
if (!isRunning){
isRunning = true; //usage of BOOLEAN!
synchronized(lock){
lock.notify();
}
}
}
Does anything seems wrong here? thanks.
Edit:
Purpose: This way when add() will be called the second time and more, it won't get blocked on notify(). Is there a better way to achieve this non blocking behavior of the main thread?
Although you do not show the addToQueue code I am fairly certain that this code will not work properly, as you are accessing the shared queue (which is not thread-safe) without any synchronization.
process(queue.remove());
Instead of trying to make your custom queue work (I doubt that your plan with the boolean flag is possible), save the time and work and use one of the BlockingQueues or ConcurrentLinkedQueue provided in the JDK.
The Queue is not synchronized and therefore the above code can suffer from the lost wake-up call typical for conditional variables and monitors. https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem
For example, here is a problematic sequence:
At the beginning of the run the Q is empty and isRunning is false.
Thread 1 (t1) checks if Q is empty (which is true) and then stops running.
Than Thread 2 (t2) starts running and execute the addToQ method.
and then t1 continues running and waits on the lock although the Q is not empty.
If you want a non-blocking solution you can use the non-blocking Q java is offering (http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentLinkedQueue.html)Of course, you can use java own blockingQueue, but this is blocking.

Categories