What is Busy Spin : Busy spinning is a waiting strategy in which one thread loop continuously to check certain condition and waiting for other thread to change this condition to break the loop without releasing CPU so that waiting thread can proceeds its work further.
Traditional threading methods like sleep,Wait () & notify() releases the CPU but busy spin does not relinquish CPU and hence preserves CPU caches.
Impact on performance in Busy Spin: Busy spin is bad for performance point of view as one thread continuously running in loop until condition given in the loop becomes false without releasing CPU and hence consuming resources and waste CPU cycles.
Solution to avoid busy spin : To avoid busy spin we must use wait() and notify() method . Calling Wait() method will release CPU and let thread to wait for notify() signal by other thread .This waiting strategy will avoid wasteful consumption of CPU cycles as in busy spin.
Program to demonstrate Busy spin :
In this program , we are using busy spin strategy in Producer- consumer problem. When producer is done with production after that it will change boolean flag ‘isProgress’ to false. Now, busy spin strategy is used inside run method of consumer . It continuously checking the value of boolean flag ‘isProgress’ and when this value becomes false then consumer thread will breaks the loop condition and proceeds with its task to consume products as given in below example.
1 2 3 4 5 6 7 8 9 10 11 |
public class BusySpinDemo { public static void main(String args[]){ Producer producer=new Producer(); Consumer consumer=new Consumer(producer); Thread producerThread=new Thread(producer,"prodThread"); Thread consumerThread=new Thread(consumer,"consThread"); producerThread.start(); consumerThread.start(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import java.util.ArrayList; class Producer implements Runnable { boolean isProgress; ArrayList<Integer> proList; Producer(){ isProgress=true; proList=new ArrayList<>(); } @Override public void run(){ for(int i=1;i<=8;i++){ proList.add(i); System.out.println("Producer is still Producing, Produced : "+i); try{ Thread.sleep(500); }catch(InterruptedException e){e.printStackTrace();} } isProgress=false; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Consumer extends Thread { Producer producer; Consumer(Producer prod){ this.producer=prod; } @override public void run(){ while(this.producer.isProgress){ System.out.println("BUSY SPIN condition."); } System.out.println("Consumer starts consuming products."); int size=this.producer.proList.size(); for(int i=0;i<size;i++){ System.out.println("Consumed : "+ this.producer.proList.remove(0) +" "); } } } |
Output:
BUSY SPIN condition.
Producer is still Producing, Produced : 1
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Producer is still Producing, Produced : 2
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Producer is still Producing, Produced : 3
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Producer is still Producing, Produced : 4
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Producer is still Producing, Produced : 5
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Producer is still Producing, Produced : 6
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Producer is still Producing, Produced : 7
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Producer is still Producing, Produced : 8
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
BUSY SPIN condition.
Consumer starts consuming products.
Consumed : 1
Consumed : 2
Consumed : 3
Consumed : 4
Consumed : 5
Consumed : 6
Consumed : 7
Consumed : 8
What if we use wait() Notify() method in above Producer-Consumer Problem:
In this program, producer use notify() method to notify Consumer that producer is done with the production and now consumer can consume products. Inside run() method of consumer we are using wait() method in place of busy spin condition as we are using in above example. Please check output below for wait() and notify() method.
1 2 3 4 5 6 7 8 9 10 11 12 |
public class BusySpinDemo { public static void main(String args[]) { Producer producer=new Producer(); Consumer consumer=new Consumer(producer); Thread producerThread=new Thread(producer,"prodThread"); Thread consumerThread=new Thread(consumer,"consThread"); producerThread.start(); consumerThread.start(); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import java.util.ArrayList; class Producer implements Runnable { ArrayList<Integer> proList; Producer(){ proList=new ArrayList<>(); } @Override public void run(){ synchronized (this) { for(int i=1;i<=8;i++){ proList.add(i); System.out.println("Producer is still Producing, Produced : "+i); try{ Thread.sleep(500); }catch(InterruptedException e){e.printStackTrace();} } this.notify(); } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
class Consumer extends Thread { Producer producer; Consumer(Producer prod){ producer=prod; } @override public void run(){ synchronized (this.producer) { try { this.producer.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("Consumer starts consuming products."); int size=this.producer.proList.size(); for(int i=0;i<size;i++){ System.out.println("Consumed : "+ this.producer.proList.remove(0) +" "); } } } |
OutPut:
Producer is still Producing, Produced : 1
Producer is still Producing, Produced : 2
Producer is still Producing, Produced : 3
Producer is still Producing, Produced : 4
Producer is still Producing, Produced : 5
Producer is still Producing, Produced : 6
Producer is still Producing, Produced : 7
Producer is still Producing, Produced : 8
Consumer starts consuming products.
Consumed : 1
Consumed : 2
Consumed : 3
Consumed : 4
Consumed : 5
Consumed : 6
Consumed : 7
Consumed : 8
When to use Busy Spin :
Busy spin is used in multicore processors where it is possible that a paused thread can resume on different core and this thread will use old cache and there is no need to rebuild cache as CPU is not released in busy spin.
It is used in trading applications where waiting time between two message is very less and frequent.
Leave a Reply