RFR 8034168: ThreadMXBean/Locks.java failed, blocked on wrong object
Martin Buchholz
martinrb at google.com
Thu Feb 20 09:04:25 PST 2014
I think David is too pessimistic about Thread.yield being ineffective on
Java SE implementations (OTOH David is a Java Embedded expert). In
practice an implementation that never thread switched out of a yield() loop
would not pass the tck. As for theory: it's true that Thread.yield has no
progress guarantees, but then neither does Thread.sleep. A perverse
implementation can always starve any thread it feels like.
Anyways, there is nothing wrong with your sleep loop. Except maybe you
want to time out eventually.
On Thu, Feb 20, 2014 at 6:16 AM, Jaroslav Bachorik <
jaroslav.bachorik at oracle.com> wrote:
> This was discussed when reviewing ThreadMXBean/
> SynchronizationStatistics.java
>
> Regarding a busy wait checking the thread states and issuing
> Thread.yield() now and then David Holmes wrote:
> "Not elegant and not completely reliable either. Probably adequate on a
> multi-core system but single-core and with some schedulers it could just
> be a busy spin." [1]
>
> As far as I understand, the only benefit of using Thread.yield() instead
> of Thread.sleep() would be 10-100ms shorter execution time, right?
>
> -JB-
>
> [1] http://mail.openjdk.java.net/pipermail/jmx-dev/2013-
> October/000484.html
>
>
> On 19.2.2014 17:56, Martin Buchholz wrote:
>
>> The jsr166 tck tests make systematic use of Thread.yield, e.g.
>>
>>
>> /**
>> * Spin-waits up to the specified number of milliseconds for the
>> given
>> * thread to enter a wait state: BLOCKED, WAITING, or TIMED_WAITING.
>> */
>> void waitForThreadToEnterWaitState(Thread thread, long
>> timeoutMillis) {
>> long startTime = System.nanoTime();
>> for (;;) {
>> Thread.State s = thread.getState();
>> if (s == Thread.State.BLOCKED ||
>> s == Thread.State.WAITING ||
>> s == Thread.State.TIMED_WAITING)
>> return;
>> else if (s == Thread.State.TERMINATED)
>> fail("Unexpected thread termination");
>> else if (millisElapsedSince(startTime) > timeoutMillis) {
>> threadAssertTrue(thread.isAlive());
>> return;
>> }
>> Thread.yield();
>> }
>> }
>>
>>
>>
>> On Tue, Feb 18, 2014 at 11:29 PM, Jaroslav Bachorik <
>> jaroslav.bachorik at oracle.com> wrote:
>>
>> On 18.2.2014 18:06, Martin Buchholz wrote:
>>>
>>> Not checking any details, but tests that want to wait for a particular
>>>> thread state are a good reason to use
>>>>
>>>> volatile boolean flag;
>>>> ...
>>>> while (!flag) Thread.yield();
>>>>
>>>> I prefer calling Thread.yield to sleeping in this special case, in part
>>>> because I don't want to rely on the implementation of sleep, while yield
>>>> is
>>>> semantically a no-op. (Also sleeping 100ms is a long time for a
>>>> computer)
>>>>
>>>>
>>> There were discussions for a similar fix regarding Thread.yield(). The
>>> concern was that using Thread.yield() in a tight loop might very easily
>>> lead to starvation on single core machines. Therefore Thread.sleep(10) is
>>> used to be sure the flag setting thread has actually a chance to
>>> progress.
>>>
>>> -JB-
>>>
>>>
>>>
>>>
>>>>
>>>> On Tue, Feb 18, 2014 at 8:22 AM, Jaroslav Bachorik <
>>>> jaroslav.bachorik at oracle.com> wrote:
>>>>
>>>> Please, review the following test change.
>>>>
>>>>>
>>>>> Issue : https://bugs.openjdk.java.net/browse/JDK-8034168
>>>>> Webrev: http://cr.openjdk.java.net/~jbachorik/8034168/webrev.00
>>>>>
>>>>> The test fails because of falsely evaluating the thread being parked as
>>>>> actually waiting on a monitor. This is because there is no difference
>>>>> in
>>>>> java thread state for those two situations. The test is using Phaser
>>>>> for
>>>>> synchronization between the checked and checking thread to make sure an
>>>>> appropriate code section is entered before performing asserts. Then it
>>>>> checks the checked thread state and waits till it becomes WAITING.
>>>>> Unfortunately, when Phaser needs to wait it parks the thread and sets
>>>>> the
>>>>> thread state to WAITING. From now on the test is in a completely random
>>>>> state and the result will largely depend on timing - thus failing
>>>>> intermittently.
>>>>>
>>>>> The solution is to use an additional volatile variable to prevent
>>>>> falsely
>>>>> indicating the park() induced WAITING state.
>>>>>
>>>>> Thanks,
>>>>>
>>>>> -JB-
>>>>>
>>>>>
>>>>>
>>>>
>>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.openjdk.java.net/pipermail/serviceability-dev/attachments/20140220/f1162adc/attachment.html
More information about the serviceability-dev
mailing list