JDK-4148125 : Thread.join() completes too early
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.1.6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 1998-06-12
  • Updated: 1998-06-19
  • Resolved: 1998-06-19
Related Reports
Duplicate :  
Description

Name: mf23781			Date: 06/12/98


Thread.join() completes before thread ceases execution. 

Thread.join() should not complete until the receiving thread has died.
However, in the current versions of  the JDK, Thread.join() completes 
as soon as stop() has been issued, rather than when the receiving  
thread has completed execution.  

//
// Thread.join() completes too early.
//
// The documentation for Thread.join() states:
//    "Waits for this thread to die."
//
// "thread died" should imply that the instruction pointer associated with the
// thread never changes again. However, Thread.join() does not implement these semantics.
//
// A thread which has been stopped may not die immediately because a finally clause on its
// stack may be blocked or otherwise delayed for legitimate reasons. However, Thread.join()
// returns immediately for such threads even if the instruction pointer for the thread will change
// subsequently (i.e. more code is executed).
//
// It seems reasonable that Thread.join() should not complete until the thread is truly dead
// as opposed to "almost dead" otherwise the caller cannot make any strong assertions about what
// what other concurrent activity may be in progress.
//
// To compile: java Bug2.java
//

public class Bug2 implements Runnable
{
   private boolean running;
   private boolean finished;

   public Bug2()
   {
      running = false;
      finished = false;
   }

   public synchronized void waitUntilRunning() throws InterruptedException
   {
      while (!running) {
         wait();
      }
   }

   public synchronized void waitUntilFinished() throws InterruptedException
   {
      while (!finished) {
         wait();
      }
   }


   public void run()
   {
      try {

         synchronized (this) {

            running = true;
            notifyAll();

            try {
               while (true) {
                  wait();
               }
            } catch (InterruptedException e) {
            }

         }

      } finally {

         try {
            Thread.sleep(2000);
         } catch (InterruptedException e) {
         }

         synchronized (this) {
            finished = true;
            notifyAll();
         }
      }

   }

   private static void test()
   {
         Thread   t1;

         Bug2   b2;

         try {

            b2 = new Bug2();

            t1 = new Thread(b2, "t1");

            t1.start();

            b2.waitUntilRunning();

            t1.stop();
            t1.join();

            synchronized (b2) {
               if (!b2.finished) {
                  if (!t1.isAlive()) {
                     System.err.println("failed...isAlive() does not match actual thread state");
                  }
                  System.err.println("failed...t1.join() finished prematurely");
                  b2.waitUntilFinished();
               } else {
                  System.out.println("passed");
               }
            }

         } catch (InterruptedException i) {
         }
   }

   public static void main(String args[])
   {
      test();
   }

}

Discovered on AIX 1.1.6, but also happens on NT 1.1.6, 
1.1.7A and 1.2beta4H
======================================================================

Comments
WORK AROUND Name: mf23781 Date: 06/12/98 The defect raiser has created an alternative implementation of the JLS thread specification that implements the specification reliably. ======================================================================
11-06-2004