Review request for 8022208: Intermittent test failures in java/lang/Thread/

Mandy Chung mandy.chung at
Fri Nov 1 03:32:06 UTC 2013

On 10/31/2013 5:38 PM, David Holmes wrote:
> Hi Mandy,
> On 1/11/2013 5:11 AM, Mandy Chung wrote:
>> Updated webrev that has a new
>> test/lib/testlibrary/ and also change to use
>> AtomicInteger:
> Sorry but I don't see how this works - and that applies to the old 
> version too! (Which I know I've looked at before so this is somewhat 
> unsettling for me :( ).
> First I found it confusing to track which thread was which in the 
> refactoring (which in itself is a good idea). Inside 
> ThreadStateController "myThread" doesn't mean anything - that comes 
> from the calling context - I suggest changing to refer to "this 
> thread" or "the current thread" as appropriate. eg "Have the current 
> thread wait until this thread is about to block" or whatever is needed.

I wasn't happy with "myThread" too and should rename it.

> Looking at an actual test we have eg:
>    myThread.goWaiting();
>   ThreadStateController.checkThreadState(myThread, Thread.State.WAITING);
> First: why is checkThreadState static rather than just an instance 
> method?

Yes it can.

> So goWaiting is supposed to tell myThread to go to a "waiting" state 
> so that the main thread can then verify that. Lets assume for 
> arguments sake that the thread is currently RUNNABLE so it is 
> currently looping around in run() doing the little math exercise. 
> goWaiting does:
>   public void goWaiting() {
>     System.out.println("Waiting myThread to go waiting.");
>     setState(WAITING);
>     // wait for MyThread to get to just before wait on object.
>     phaser.arriveAndAwaitAdvance();
>  }
> and setState does:
>    case WAITING:
>    case TIMED_WAITING:
>        state = newState;
>        synchronized (lock) {
>           lock.notify();
>        }
>        break;
> so as soon as we update "state" myThread is capable of changing what 
> it is doing in run() to:
>    case WAITING: {
>       synchronized (lock) {
>          // signal main thread.
>          phaser.arrive();
>          System.out.println("  myThread is going to wait.");
>          try {
>              lock.wait();
>           } catch (InterruptedException e) {
>              // ignore
>              interrupted.incrementAndGet();
>           }
>       }
>       break;
> so now we have a race between the two threads to see who can grab the 
> lock first. If it is the main thread then we issue a notify when 
> nothing is waiting and so the subsequent wait() by myThread will 
> potentially wait forever. At least in that case the main thread will 
> see that it is waiting!
> If "myThread" wins the race it will wait after signalling the phaser 
> and the main thread will then issue the notify allowing myThread to 
> proceed (and do what? process the WAITING case again??). So there is 
> no guarantee that myThread will be waiting when the main thread checks 
> the state!
> Similarly for issuing the unpark in the parking cases.
> AFAICS the basic approach here should be:
> - tell myThread to go to state X
> - wait until myThread should be in state X
> - verify myThread is in state X
> - allow myThread to escape from state X
> but this code does the last step second.
> ???

I was looking at the intermittent failures and fix the problem I 
identified.   What you said above is definitely potential race that I 
didn't have analyzed the waiting state thoroughly.  It's time to revisit 
the whole test and see if there is a better way to code this.

thanks for the review.

More information about the core-libs-dev mailing list