Path: csiph.com!usenet.pasdenom.info!gegeweb.org!eternal-september.org!feeder.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail From: Eric Sosman Newsgroups: comp.lang.java.programmer Subject: Re: java.util.concurrent.atomic Date: Tue, 29 Oct 2013 17:27:42 -0400 Organization: A noiseless patient Spider Lines: 51 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit Injection-Date: Tue, 29 Oct 2013 21:27:42 +0000 (UTC) Injection-Info: mx05.eternal-september.org; posting-host="858a9d65d95f4ea4d355bd116aa2cdbf"; logging-data="30304"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+yG5pONikxCgWZMNgHiu1h" User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:24.0) Gecko/20100101 Thunderbird/24.0.1 In-Reply-To: Cancel-Lock: sha1:rQXFdXnSn2x+zjcZcrD3hgLktdE= Xref: csiph.com comp.lang.java.programmer:26451 On 10/29/2013 4:35 PM, Andreas Leitgeb wrote: > Kevin McMurtrie wrote: >> Why use code that can never block? [...] > > That would be fine, if the code really didn't block, but if it > ends up doing the "do { ... } while (...)" idiom, then it really > IS blocking, just in a bad way. > > What would be usecases of non-blocking synchronisation that don't > end up polling until success? Marcel Müller described one elsethread. Yes, after a failure the non-blocking algorithm goes back and tries again. What you may have missed is that it tries again with a new "new value," and doesn't simply try again with the same old failed one: while (true) { Thing oldThing = currentThing; Thing newThing = modifiedVersionOf(oldThing); // Done atomically by compare-and-swap: if (currentThing == oldThing) { // No other thread got there before me, so: currentThing = newThing; break; } else { // Rats! Somebody else changed currentThing, so // the newThing I computed is already obsolete. // Go back and try *everything* again. } } The advantage of this approach is that you don't need to hold a lock for however long modifiedVersionOf() takes. The disadvantage is that currentThing might change during that time, meaning your effort was wasted. In principle you could stay in the loop "forever" if other threads are constantly updating currentThing -- but a blocking algorithm wouldn't remove that pain, it would just distribute it differently (threads could wait "forever" before acquiring a lock). If currentThing is constantly getting updated, you at least know that *some* thread is making progress even if it's not *your* thread ... On the other hand, blocking code is a good deal easier to write and understand. I took a week-long course on non-blocking algorithms from an ACM Fellow, and the main thing I learned is that you pretty much *need* to be an ACM Fellow to avoid blunders ... -- Eric Sosman esosman@comcast-dot-net.invalid