javamultithreadingbusy-waiting

Java Threads Busy Waiting


Hi I am doing a project and I have reached a part where I am very stuck. I have tried to search for ways to learn how to write the while loop for a busy wait but I haven't found anything and my code just runs as an infinite loop. Can someone help explain to me how a busy waiting loop should work and help me break out of this infinite loop?

The project wants the following to happen: In the morning, after the student wakes up (it will take a random time) he will head to the bathroom to get ready for a new school day. If the bathroom is already taken, the student takes a break (use yield()) and later on he will wait (use busy waiting) for the bathroom to become available. Students will use the bathroom in a First Come First Serve basis (you can use a Boolean array/vector for having them released in order).

 public class Student implements Runnable 
    {
        private Random rn = new Random();
        private String threadNum;
        private volatile boolean bathroomFull = false;
        private static long time = System.currentTimeMillis();
        private Thread t;


    public Student(String studentID) 
    {
      threadNum = studentID;

      t = new Thread(this, "Student Thread #"+threadNum);
      System.out.println("thread created = " + t);
      // this will call run() function
      t.start();
   }

   public void run() 
   {
       int waitTime = rn.nextInt(4000 - 2000 + 1)+2000;

        System.out.println( "the current time is " + (System.currentTimeMillis() - time) + "and the wait time is: " +waitTime );

         //Student wakes up after random time
        while((System.currentTimeMillis()-time) < waitTime)
       {
          // System.out.println("the remaining sleep time is " + (System.currentTimeMillis()-time));
            ;
       }

      int a = rn.nextInt(4000 - 2000 + 1)+2000;
      try 
      {
          //System.out.println("I'm going to sleep for " +a + " milliseconds");
        Thread.sleep(a);
      } 
      catch (InterruptedException e) 
      {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }

      //this is the busy wait loop where is the bathroom is full then a thread will yield until it is available
    int l = rn.nextInt(10 - 1)+1;
  bathroomFull = true;

      while(bathroomFull)
        {
          for(int j = 0; j < l; j++)
          {
              System.out.println("i am in the bathroom for " + l + "minutes " + Thread.currentThread());
          }
          Thread.yield();
          bathroomFull = false;
          //exitBathroom();

        }
    bathroomFull = true;

This is my main method which allows the user to specify how many student threads they want. And yes i don't understand how to implement the change of the value so that the busy wait while loop can be broken.

 public static void main(String args[]) 
   {
       int numberOfStudents;
       numberOfStudents = Integer.parseInt(JOptionPane.showInputDialog("How many students are there in the university? "));
      // System.out.println("there are " + numberOfStudents);

       for(int i = 0; i < numberOfStudents; i++)
       {   
           new Student(String.valueOf(i+1));
       }
          new Teacher();
   }

Solution

  • Here is a working example of a busy wait. It uses an AtomicBoolean to indicate if the bathroom is occupied or not. Atomic operations are executed in one step, this is important to guarantee thread-safety. We could also use a normal boolean and write compareAndSet ourselves:

    private static synchronized boolean compareAndSet(boolean expected, boolean value) {
        if (occupied == expected) { // (1)
            occupied = value; // (2)
            return true;
        } else {
            return false;
        }
    }
    

    This is the equivalent (for this example) of the Java implementation. synchronized is needed otherwise it would be possible that two threads succeed the test at (1) before (2) was executed (because those 2 operations aren't atomic) and then two people would go in the bathroom together...

    import java.util.concurrent.atomic.AtomicBoolean;
    
    public class Student extends Thread {
    
        // note the static: there is only one bathroom for all students
        private static AtomicBoolean occupied = new AtomicBoolean(false);
    
        private String name;
    
        public Student(String name) {
            this.name = name;
        }
    
        private void sleep(int millis) {
            try {
                Thread.sleep(millis);
            } catch (InterruptedException e) {
                System.out.println(name + " wet his/her pants");
            }
        }
    
        @Override
        public void run() {
            int r = (int)(Math.random() * 5000);
            System.out.println(name + " sleeps for " + r + " ms");
            sleep(r);
            System.out.println(name + " goes to bathroom");
            // ***** busy wait *****
            while (!occupied.compareAndSet(false, true)) {
                System.out.println(name + " takes a break");
                Thread.yield();
                sleep(1000);
            }
            // ***** end (in bathroom) *****
            System.out.println(name + " is in the bathroom");
            sleep(1000);
            occupied.set(false);
            System.out.println(name + " goes to university");
        }
    
        public static void main(String[] args) {
            new Student("Bob").start();
            new Student("Alice").start();
            new Student("Peter").start();
            new Student("Marcia").start();
            new Student("Desmond").start();
            new Student("Sophia").start();
        }
    
    }
    

    possible output:

    Bob sleeps for 2128 ms
    Marcia sleeps for 3357 ms
    Alice sleeps for 1289 ms
    Peter sleeps for 820 ms
    Desmond sleeps for 1878 ms
    Sophia sleeps for 2274 ms
    Peter goes to bathroom
    Peter is in the bathroom
    Alice goes to bathroom
    Alice takes a break
    Peter goes to university
    Desmond goes to bathroom
    Desmond is in the bathroom
    Bob goes to bathroom
    Bob takes a break
    Sophia goes to bathroom
    Sophia takes a break
    Alice takes a break
    Desmond goes to university
    Bob is in the bathroom
    Sophia takes a break
    Alice takes a break
    Marcia goes to bathroom
    Marcia takes a break
    Bob goes to university
    Sophia is in the bathroom
    Alice takes a break
    Marcia takes a break
    Sophia goes to university
    Alice is in the bathroom
    Marcia takes a break
    Alice goes to university
    Marcia is in the bathroom
    Marcia goes to university