On Saturday, September 3, 2016, <fo...@univ-mlv.fr> wrote: > > De: "Dr Heinz M. Kabutz" <he...@javaspecialists.eu <javascript:;>> > > À: "Remi Forax" <fo...@univ-mlv.fr <javascript:;>> > > Cc: "Ivan Gerasimov" <ivan.gerasi...@oracle.com <javascript:;>>, > "core-libs-dev" > > <core-libs-dev@openjdk.java.net <javascript:;>> > > Envoyé: Samedi 3 Septembre 2016 19:10:19 > > Objet: Re: A bit of sugar for j.u.c.locks with try-with-resources? > > > Not sure why the discussion keeps on going to EA with try-with-resource > with > > locks. > > > 1. There is no reason to construct objects, for example just write this > class: > > > import java.util.concurrent.locks.*; > > > public class AutoLock implements AutoCloseable { > > private final Lock lock; > > > public AutoLock(Lock lock) { > > this.lock = lock; > > } > > > public AutoLock lock() { > > lock.lock(); > > return this; > > } > > > public void close() { > > lock.unlock(); > > } > > } > > > And then use it as such: > > > import java.util.concurrent.locks.*; > > > public class AutoLockTest { > > private final Lock lock = new ReentrantLock(); > > private final AutoLock al = new AutoLock(lock); > > > public void doSomething() { > > try (AutoLock temp = al.lock()) { > > // do something on the state > > } > > } > > } > > > No objects are constructed. > yes, you still pay the cost of an extra field in the class, an extra > indirection when calling lock and unlock and an extra nullcheck (this one > is hidden in the implementation of a try-with-resources). > You may answer that ReentrantLock already pay the cost of an indirection > over an AbstractQueuedSynchronizer (because a lock can be fair or unfair) > so i suppose that an unfair implementation of AutoLock that directly > extends AbstractQueuedSynchronizer should be faster or as fast as a > ReentrantLock.
Right. This particular example can be worked around by having an extra field. But it's a hack that besides the issues Remi lists, extends an object's lifetime unnecessarily. You want sugar/ergonomics for the try/finally usage, not anything beyond that. > > > 2. No one uses ReentrantLock anyway (unless they absolutely have to). > See the > > comment in Java 9 CopyOnWriteArrayList :-) > > /** > > * The lock protecting all mutators. (We have a mild preference > > * for builtin monitors over ReentrantLock when either will do.) > > */ > > final transient Object lock = new Object(); > yes, synchronized is more versatile until you have contention, want > fairness, a tryLock or several Conditions. Or lock and unlock aren't in the same scope/control flow. > > > 3. If you were to construct objects in the TWR block, they would be > escaped in > > my experience, except in the one case where there are multiple threads > trying > > to lock at the same time. However, in that case, ReentrantLock will > anyway > > create objects to manage the contention. But it really is a non-issue, > since it > > is trivial to code to not construct any objects with the TWR block in > the first > > place. Again, in this particular case it's a non issue besides the downsides already mentioned. Not all cases will be like that (e.g. you may receive a resource as an arg and not have access to it anywhere else, and want the ergonomics). > > > I keep getting asked this question all over the world. Personally I > think it's a > > non-issue, since the code is so trivial to write yourself, plus so few > people > > would use ReentrantLock anyway. > > Regards I know Kris started the thread in the context of a lock (and let's not forget it could be some other impl besides RL), but there's a more general pattern that's being discussed. > > regards, > Rémi > > > Heinz > > -- > > Dr Heinz M. Kabutz (PhD CompSci) > > Author of "The Java(tm) Specialists' Newsletter" > > Sun/Oracle Java Champion since 2005 > > JavaOne Rock Star Speaker 2012 http://www.javaspecialists.eu Tel: +30 > 69 75 595 > > 262 > > Skype: kabutz > > > Remi Forax wrote: > >> ----- Mail original ----- > > >>> De: "Ivan Gerasimov" <ivan.gerasi...@oracle.com <javascript:;>> À: > "Krystal Mok" > >>> <rednaxel...@gmail.com <javascript:;>> , "core-libs-dev" < > core-libs-dev@openjdk.java.net <javascript:;>> > >>> Envoyé: Samedi 3 Septembre 2016 12:23:28 > >>> Objet: Re: A bit of sugar for j.u.c.locks with try-with-resources? > > >>> Hi Krystal! > > >>> On 03.09.2016 5:41, Krystal Mok wrote: > > >>>> Hi core-libs developers, > > >>>> I mostly live down in the VM world, but recently I've been playing > with > >>>> j.u.c.locks a bit, and saw that there's an opportunity to retrofit > the API > >>>> with the try-with-resources syntax. I wonder if anybody has brought > this > >>>> topic up before; apologies if there had been. > > >>>> >From the JavaDoc of j.u.c.l.ReentrantLock, the following is a > typical usage: > > >>>> class X { > >>>> private final ReentrantLock lock = new ReentrantLock(); > >>>> // ... > > >>>> public void m() { > >>>> lock.lock(); // block until condition holds > >>>> try { > >>>> // ... method body > >>>> } finally { > >>>> lock.unlock() > >>>> } > >>>> } > >>>> } > > >>> It could be written as > >>> public void m() { > >>> lock.lock(); // block until condition holds > >>> try (Closeable unlocker = lock::unlock) { > >>> // ... method body > >>> } > >>> } > > >>> This would save a couple of lines of code. > > >> but it does an allocation (if the escape analysis fails), > >> i think it's better to wait for proper value types :) > > >>> With kind regards, > >>> Ivan > > >> regards, > >> Rémi > > >>>> The try...finally construction really pops out as a try-with-resources > >>>> candidate. > > >>>> So what if we retrofit that with something like: > > >>>> class X { > >>>> private final ReentrantLock lock = new ReentrantLock(); > >>>> // ... > > >>>> public void m() { > >>>> try (lock.lock()) { // block until condition holds > >>>> // ... method body > >>>> } // automatic unlock at the end > >>>> } > >>>> } > > >>>> Assuming lock.lock() returns a temporary wrapper object (let's call > it a > >>>> "Locker" for this discussion), where Locker implements AutoCloseable, > and > >>>> its close() method calls lock.unlock(). > >>>> That'll make the API look and feel quite similar to the built-in > >>>> "synchronized () { ... }" syntax. With escape analysis and scalar > >>>> replacement implemented correctly in the VM, this temporary Locker > object > >>>> wouldn't incur much (or any) runtime cost after optimized JIT'ing, so > it > >>>> feels like a pure win to me. > > >>>> What do you think? > > >>>> Best regards, > >>>> Kris (OpenJDK username: kmo) > -- Sent from my phone