Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: updated condition NCCE/CS set

...

This noncompliant code example demonstrates a complex multi-step process being undertaken by several threads. Each thread executes one step of the process; the step being currently performed is maintained by the step field. Each thread waits for the step field to indicate that it is time to perform that thread's step. When it is time to perform its step, each thread does so. It then increments step for the next thread, notifies the thread, and exits.

Code Block
bgColor#FFcccc
public class SleepyThreadProcessStep implements Runnable {
  private static final Object lock = new Object();
  private static int time = 1;
  private int myStep; // do stuff when the step raches this value

  public SleepyThreadProcessStep(int myStep) {
    this.myStep = myStep;
  }

  public void run () {
    try {
      synchronized (lock) {
        while (time != myStep) { 
          lock.wait();  
        }

        // ... do stuff

        time++;
        lock.notify();
      }
    } catch (InterruptedException ie) {
      Thread.currentThread().interrupt(); // Reset interrupted status
    }    
  }

  public static void main(String[] args) {
    for (int i = 5; i > 0; i--) {
      SleepyThreadProcessStep ms = new SleepyThreadProcessStep(i);
      new Thread(ms).start();
    }
  }
}

...

Code Block
bgColor#ccccff
  public void run () {
    try {
      synchronized (lock) {
        while (time != myStep) { 
          lock.wait();  
        }

        // ... do stuff

        time++;
        lock.notifyAll();
      }
    } catch (InterruptedException ie) {
      Thread.currentThread().interrupt(); // Reset interrupted status
    }    
  }

...

This noncompliant code example derives from the previous noncompliant code example but uses the Condition interface. Field cond condition is used to let threads wait on different condition predicates.

Code Block
bgColor#FFcccc

public class ProcessStep implements Runnable {
  private static final ConditionLock condlock = new lock.newConditionReentrantLock();
// ...

public void run (){
   private static final Condition condition = lock.locknewCondition();
  
private static tryint {time = 1;
  	private int 
myStep; // do stuff if(number == 1) {	  
      while(buffer_count == 0) { when the step raches this value

  public ProcessStep(int myStep) {
    this.myStep    cond.await();		  
    = myStep;
  }  

  public void } else if(number == 2run() {
  	  lock.lock();
   		 try {
      while (buffer_counttime =!= 10myStep) {	 
        condcondition.await();  
 	    		 }

   	   // ... do stuff

  	    time++;
      }condition.signal();
    } catch (InterruptedException ie) {
    } else if(number == 3) Thread.currentThread().interrupt(); // Reset interrupted status
    } finally {
      condlock.signalunlock();	
    }
 	 }

  
public static }void catch (InterruptedException iemain(String[] args) {
    // Handle the exception
    Thread.currentThread().interrupt(); // Reset interrupted status
  } finally {
    lock.unlock();
  }
}	  for (int i = 5; i > 0; i--) {
      ProcessStep ms = new ProcessStep(i);
      new Thread(ms).start();
    }
  }
}

Similar to Object.notify(), the cond.signal() method may choose either of the threads any one thread and awaken it.

Compliant Solution (signalAll())

This compliant solution uses the signalAll() method to resume all the waiting threads whose condition predicate allows doing so.

Code Block
bgColor#ccccff

} else if(number == 3) {
  cond
  public void run() {
    lock.lock();
    try {
      while (time != myStep) { 
        condition.await();  
      }

      // ... do stuff

      time++;
      condition.signalAll();
    } catch (InterruptedException ie) {
      Thread.currentThread().interrupt(); // Reset interrupted status
    } finally {
      lock.unlock();
    }
  }

Compliant Solution (unique Condition

...

per thread)

This compliant solution uses two different condition variables full and empty to indicate whether the the buffer is full or empty, respectivelyassigns each thread its own Condition, and makes them accessible to all the threads.

Code Block
bgColor#ccccff
public class ProcessStep implements Runnable {
  private static final Lock lock = new ReentrantLock();
  private static final Condition[] fullconditions = lock.newCondition();
final Condition empty = lock.newCondition();
// ...

public void run (){
  lock.lock();  
  try {    	  
    if(number == 1) {	   new Condition[6];
  private static int time = 1;
  private int myStep; // do stuff when the step raches this value

  public ProcessStep(int myStep) {
    this.myStep = myStep;
    conditions[myStep] = lock.newCondition();
  }

  public void run() {
    lock.lock();
    try {
      while (buffer_counttime !== 0myStep) { 
        emptyconditions[myStep].await();		  
      }

  
    } else if(number == 2) {  	    		  
      while(buffer_count == 10) {	// ... do stuff

      time++;
      if (myStep + 1 < conditions.length) {
        full.awaitconditions[myStep+1].signal();
   	   }
 		   } 	catch (InterruptedException ie) {
     	    
      } Thread.currentThread().interrupt(); // Reset interrupted status
    } else if(number == 3) finally {
      emptylock.signalunlock();	
    }
  full.signal();}

  public static void  	   		  main(String[] args) {
    }for 	(int i = 
5; i }> catch (InterruptedException ie0; i--) {
    // Handle theProcessStep exception
ms = new  Thread.currentThreadProcessStep(i).interrupt(); // Reset interrupted status
  } finally {
    lock.unlocknew Thread(ms).start();
    }
}	  }
}

Even though signal() is used, it is guaranteed that only one thread will awaken because each condition predicate corresponds to a unique Condition variable.

...