Re: Regression in LinkedTransferQueue since JDK17?

Matthew Swift via Concurrency-interest <[email protected]> Thu, 7 Jul 2022 15:23:12 +0200
Newsgroups gmane.comp.java.jsr.166-concurrency
Message-ID <CANGKH601_ruahB3Oe=v9H4C=zWjX8TkbK6zR0dQSmJO6EVjaGg@mail.gmail.com>
--===============2095595847817406433==
Content-Type: multipart/alternative; boundary="00000000000084479005e336fdef"

--00000000000084479005e336fdef
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Thanks for the quick response.
I'll switch our application over to LinkedBlockingQueue for now in that
case.
Do you know if there is an existing JDK bug tracking this issue which I can
monitor to know when it's safe to switch back to LTQ? I couldn't find any
obvious bug reports among the public JIRA issues.

Kind regards,
Matt


On Wed, 6 Jul 2022 at 20:31, Dr Heinz M. Kabutz via Concurrency-interest <
[email protected]> wrote:

> I noticed today that LinkedTransferQueue is used in the
> sun.nio.ch.Poller class. Until this is fixed, would it be wiser to use
> LinkedBlockingQueue instead?
>
> Regards
>
> Heinz
> --
> Dr Heinz M. Kabutz (PhD CompSci)
> Author of "The Java=E2=84=A2 Specialists' Newsletter" - www.javaspecialis=
ts.eu
> Java Champion - www.javachampions.org
> JavaOne Rock Star Speaker
> Tel: +30 69 75 595 262
> Skype: kabutz
>
> On 2022/07/06 17:18, Doug Lea via Concurrency-interest wrote:
> > Thanks for reporting this! Sorry for problems. This anomaly/bug was a
> > byproduct of changes to better support VirtualThreads, when they were
> > being developed pre-JDK19 and there was no way distinguish them. It
> > seemed innocuous but needs fixing. Now that there are methods that
> > allow detection, we can use them here, and back-port rollback for
> > pre-JDK19.
> >
> >  -Doug
> >
> >
> > On 7/5/22 13:00, Matthew Swift via Concurrency-interest wrote:
> >> Hello!
> >>
> >> Our application contains a work queue based on LinkedTransferQueue.
> >> After some initial load, I leave the server idle only to notice that
> >> one of the subscriber threads is spinning after a period of time.
> >>
> >> I've only noticed this problem while testing on 17.0.3 as well as the
> >> version of JDK18 currently shipped with Ubuntu 22.04 LTS (build
> >> 18-ea+36-Ubuntu-1 - sorry, no idea what this version really means). I
> >> suspect the problem is related to a recent refactoring in LTQ:
> >> https://bugs.openjdk.org/browse/JDK-8246677
> >>
> >> I've managed to implement a test case that reliably fails after a few
> >> minutes (attached). When running under the debugger I can see a
> >> single subscriber thread is spinning
> >> in java.util.concurrent.LinkedTransferQueue#awaitMatch while
> >> performing a timed poll():
> >>
> >>        while ((item =3D s.item) =3D=3D e) {
> >>             if (needSweep)                               // FALSE
> >>                 sweep();
> >>             else if ((timed && nanos <=3D 0L) || w.isInterrupted()) {
> >>                 if (s.casItem(e, (e =3D=3D null) ? s : null)) {
> >>                     unsplice(pred, s);   // cancelled
> >>                     return e;
> >>                 }
> >>             }
> >>             else if (stat <=3D 0) {  // TRUE (stat =3D 0)
> >>                 if (pred !=3D null && pred.next =3D=3D s) {  // FALSE =
(pred
> >> !=3D null but pred.next !=3D s)
> >>                     if (stat < 0 &&
> >>                         (pred.isData !=3D isData || pred.isMatched()))=
 {
> >>                         stat =3D 0;
> >>                         Thread.yield();
> >>                     }
> >>                     else {
> >>                         stat =3D 1;
> >>                         s.waiter =3D w;
> >>                     }
> >>                 }
> >>             }
> >>             ...
> >>         }
> >>
> >> It's as if the subscribers race each other to poll the empty queue
> >> eventually causing one of the subscribers to get stuck in an infinite
> >> loop.
> >> Cheers,
> >> Matt
> >>
> >>
> >> _______________________________________________
> >> Concurrency-interest mailing list
> >> [email protected]
> >> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> > _______________________________________________
> > Concurrency-interest mailing list
> > [email protected]
> > http://cs.oswego.edu/mailman/listinfo/concurrency-interest
> _______________________________________________
> Concurrency-interest mailing list
> [email protected]
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>

--00000000000084479005e336fdef
Content-Type: text/html; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr">Thanks for the quick response.<div>I&#39;ll switch our app=
lication over to LinkedBlockingQueue for now in that case.</div><div>Do you=
 know if there is an existing JDK bug tracking this issue which I can monit=
or to know when it&#39;s safe to switch back to LTQ? I couldn&#39;t find an=
y obvious bug reports among the public JIRA issues.</div><div><br></div><di=
v>Kind regards,</div><div>Matt</div><div><br></div></div><br><div class=3D"=
gmail_quote"><div dir=3D"ltr" class=3D"gmail_attr">On Wed, 6 Jul 2022 at 20=
:31, Dr Heinz M. Kabutz via Concurrency-interest &lt;<a href=3D"mailto:conc=
[email protected]">[email protected]</a>&gt; =
wrote:<br></div><blockquote class=3D"gmail_quote" style=3D"margin:0px 0px 0=
px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I noticed=
 today that LinkedTransferQueue is used in the <br>
sun.nio.ch.Poller class. Until this is fixed, would it be wiser to use <br>
LinkedBlockingQueue instead?<br>
<br>
Regards<br>
<br>
Heinz<br>
-- <br>
Dr Heinz M. Kabutz (PhD CompSci)<br>
Author of &quot;The Java=E2=84=A2 Specialists&#39; Newsletter&quot; - <a hr=
ef=3D"http://www.javaspecialists.eu" rel=3D"noreferrer" target=3D"_blank">w=
ww.javaspecialists.eu</a><br>
Java Champion - <a href=3D"http://www.javachampions.org" rel=3D"noreferrer"=
 target=3D"_blank">www.javachampions.org</a><br>
JavaOne Rock Star Speaker<br>
Tel: +30 69 75 595 262<br>
Skype: kabutz<br>
<br>
On 2022/07/06 17:18, Doug Lea via Concurrency-interest wrote:<br>
&gt; Thanks for reporting this! Sorry for problems. This anomaly/bug was a =
<br>
&gt; byproduct of changes to better support VirtualThreads, when they were =
<br>
&gt; being developed pre-JDK19 and there was no way distinguish them. It <b=
r>
&gt; seemed innocuous but needs fixing. Now that there are methods that <br=
>
&gt; allow detection, we can use them here, and back-port rollback for <br>
&gt; pre-JDK19.<br>
&gt;<br>
&gt; =C2=A0-Doug<br>
&gt;<br>
&gt;<br>
&gt; On 7/5/22 13:00, Matthew Swift via Concurrency-interest wrote:<br>
&gt;&gt; Hello!<br>
&gt;&gt;<br>
&gt;&gt; Our application contains a work queue based on LinkedTransferQueue=
. <br>
&gt;&gt; After some initial load, I leave the server idle only to notice th=
at <br>
&gt;&gt; one of the subscriber threads is spinning after a period=C2=A0of t=
ime.<br>
&gt;&gt;<br>
&gt;&gt; I&#39;ve only noticed this problem while testing on 17.0.3 as well=
 as the <br>
&gt;&gt; version of JDK18 currently shipped with Ubuntu 22.04 LTS (build <b=
r>
&gt;&gt; 18-ea+36-Ubuntu-1 - sorry, no idea what this version really means)=
. I <br>
&gt;&gt; suspect the problem is related to a recent refactoring in LTQ: <br=
>
&gt;&gt; <a href=3D"https://bugs.openjdk.org/browse/JDK-8246677" rel=3D"nor=
eferrer" target=3D"_blank">https://bugs.openjdk.org/browse/JDK-8246677</a><=
br>
&gt;&gt;<br>
&gt;&gt; I&#39;ve managed to implement a test case that reliably fails afte=
r a few <br>
&gt;&gt; minutes (attached). When running under the debugger I can see a <b=
r>
&gt;&gt; single subscriber thread is spinning <br>
&gt;&gt; in=C2=A0java.util.concurrent.LinkedTransferQueue#awaitMatch while =
<br>
&gt;&gt; performing a timed poll():<br>
&gt;&gt;<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0while ((item =3D s.item) =3D=3D e) {<br=
>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (needSweep)=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =
=C2=A0 =C2=A0 =C2=A0 =C2=A0// FALSE<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 sweep();<b=
r>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 else if ((timed &amp;&am=
p; nanos &lt;=3D 0L) || w.isInterrupted()) {<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (s.casI=
tem(e, (e =3D=3D null) ? s : null)) {<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 unsplice(pred, s); =C2=A0 // cancelled<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 return e;<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 else if (stat &lt;=3D 0)=
 { =C2=A0// TRUE (stat =3D 0)<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 if (pred !=
=3D null &amp;&amp; pred.next =3D=3D s) { =C2=A0// FALSE (pred <br>
&gt;&gt; !=3D null but pred.next !=3D s)<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 if (stat &lt; 0 &amp;&amp;<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 (pred.isData !=3D isData || pred.isMatched())) {<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 stat =3D 0;<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 Thread.yield();<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 }<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 else {<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 stat =3D 1;<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 s.waiter =3D w;<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 }<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 ...<br>
&gt;&gt; =C2=A0 =C2=A0 =C2=A0 =C2=A0 }<br>
&gt;&gt;<br>
&gt;&gt; It&#39;s as if the subscribers race each other to poll the empty q=
ueue <br>
&gt;&gt; eventually causing one of the subscribers to get stuck in an infin=
ite <br>
&gt;&gt; loop.<br>
&gt;&gt; Cheers,<br>
&gt;&gt; Matt<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; Concurrency-interest mailing list<br>
&gt;&gt; <a href=3D"mailto:[email protected]" target=3D"_b=
lank">[email protected]</a><br>
&gt;&gt; <a href=3D"http://cs.oswego.edu/mailman/listinfo/concurrency-inter=
est" rel=3D"noreferrer" target=3D"_blank">http://cs.oswego.edu/mailman/list=
info/concurrency-interest</a><br>
&gt; _______________________________________________<br>
&gt; Concurrency-interest mailing list<br>
&gt; <a href=3D"mailto:[email protected]" target=3D"_blank=
">[email protected]</a><br>
&gt; <a href=3D"http://cs.oswego.edu/mailman/listinfo/concurrency-interest"=
 rel=3D"noreferrer" target=3D"_blank">http://cs.oswego.edu/mailman/listinfo=
/concurrency-interest</a><br>
_______________________________________________<br>
Concurrency-interest mailing list<br>
<a href=3D"mailto:[email protected]" target=3D"_blank">Con=
[email protected]</a><br>
<a href=3D"http://cs.oswego.edu/mailman/listinfo/concurrency-interest" rel=
=3D"noreferrer" target=3D"_blank">http://cs.oswego.edu/mailman/listinfo/con=
currency-interest</a><br>
</blockquote></div>

--00000000000084479005e336fdef--

--===============2095595847817406433==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

_______________________________________________
Concurrency-interest mailing list
[email protected]
http://cs.oswego.edu/mailman/listinfo/concurrency-interest

--===============2095595847817406433==--