Tuesday, 14 June 2016

Busy spinning in multi-threading

Busy spinning or busy wait in a multi-threaded environment is a technique where other threads loop continuously waiting for a thread to complete its task and signal them to start.

while(spinningFlag){
 System.out.println("Waiting busy spinning");
}
// Reached here means spinningFlag is false… Now thread can start

Impact of Busy Spinning on performance

Busy spinning is wasteful of CPU cycles as thread just keep running in a loop unless the condition given in the loop satisfies. The main thing to note here is thread doesn't relinquish the CPU control as would be the case if wait(), sleep(), yield() methods are used where the thread gives up the CPU.

Busy spinning may give some advantage in multi-core processors. If a thread relinquishes CPU, the CPU cache for the thread where the thread state, data are stored will also be lost, if the thread resumes its operation on another CPU. In that case it has to rebuild the cache again.

Since thread doesn't relinquish control over CPU when busy spinning so the time spent to create cache again is saved.

But overall it is not a good strategy and should be avoided. At least for the application programs.

Example code

Let's write a Producer - Consumer Java program using busy spinning. Here Producer thread will put 5 elements in the list, consumer thread will be busy waiting until all the 5 elements are added by the producer thread.

import java.util.ArrayList;
import java.util.List;

public class BusySpinDemo {
    
    public static void main(String[] args) {
        ProdThread pt = new ProdThread();
        Thread t1 = new Thread(pt, "Producer");
        // passing producer thread in consumer thread
        Thread t2 = new Thread(new ConThread(pt), "Consumer");
        t1.start();
        t2.start();    
    }
}

// Producer thread
class ProdThread implements Runnable{
    List<Integer> sharedListObj;
    boolean flag;
    ProdThread(){
        System.out.println("Constructor ProdThread");
        this.sharedListObj = new ArrayList<Integer>();
        this.flag = true;
    }
    @Override
    public void run() {
        System.out.println(" ProdThread run");
        for(int i = 0; i < 5; i++){
            System.out.println("Adding to queue - " + Thread.currentThread().getName() + " " + i);
            sharedListObj.add(i);
        }
        flag = false;        
    }            
}

// Consumer thread
class ConThread implements Runnable{
    ProdThread pt;
    ConThread(ProdThread pt){
        System.out.println("Constructor ConThread");
        this.pt = pt;
    }
    @Override
    public void run() { 
      // Busy spinning loop   
        while(this.pt.flag){
            System.out.println("Waiting busy spinning");
        }
        System.out.println("Consumer starting");
        for(Integer i: this.pt.sharedListObj){
            System.out.println("" + i);
        }
    }
}

Output

Constructor ProdThread
Constructor ConThread
 ProdThread run
Waiting busy spinning
Waiting busy spinning
Waiting busy spinning
Waiting busy spinning
Waiting busy spinning
Adding to queue - Producer 0
Waiting busy spinning
Waiting busy spinning
Adding to queue - Producer 1
Waiting busy spinning
Waiting busy spinning
Waiting busy spinning
Waiting busy spinning
Adding to queue - Producer 2
Waiting busy spinning
Waiting busy spinning
Adding to queue - Producer 3
Waiting busy spinning
Adding to queue - Producer 4
Waiting busy spinning
Consumer starting
0
1
2
3
4

Note that the output is curtailed here - Deleted many "Waiting busy spinning" SOPs.

That's all for this topic Busy spinning in multi-threading. If you have any doubt or any suggestions to make please drop a comment. Thanks!


Related Topics

  1. ConcurrentLinkedDeque in Java
  2. ConcurrentLinkedQueue in Java
  3. AtomicInteger in Java Concurrency
  4. Synchronization in Java multithreading
  5. ReentrantReadWriteLock in Java
  6. Java Concurrency interview questions

You may also like -

No comments:

Post a Comment