<div dir="ltr">Hello.<br><br>Thank you very much Pavel for helping me find more information about this.<br><br>After some research (mainly by Pavel) we found a thread, with subject "<i>Default Functions for Lock Interface</i>", from October 2013 that discussed this exact thing. I don't believe that this thread is available on the internet, but I may be wrong.<br><br>In this thread, two approaches were discussed.<br><ol><li>Add support for the try-with-resources</li><li>Add default methods to the Lock interface</li></ol><br>The second approach makes use of lambda functions which incur performance cost when data is modified within the lambda function, as described by Brian Goetz in the same thread (on the 8th of October 2013).<br><div><br></div><div>---<br></div><i>When you write a method like<br><br>void withLock(Runnable)<br><br>the Runnable is going to have side-effects. So its going to be a capturing lambda -- one that captures variables from its scope:<br><br>withLock( () -> { counter++; } ); // counter is captured<br><br>With the current implementation of lambda, evaluating (not invoking) a capturing lambda expression will cause an allocation. Whereas the hand-unrolled version:<br><br>lock.lock();<br>try { counter++; } <br>finally { lock.unlock(); }<br><br>does not. The sort of things people do with locks are generally pretty performance-sensitive, so such an API was deemed, at the current time, to be an "attractive nuisance."<br></i>---<br><br><div>Almost 10 years have passed since this was originally suggested. Have enough things changed since then, that would make this approach feasible? <br></div><br><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature">With kind regards,<br>Albert Attard</div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, 21 Aug 2023 at 15:33, John Hendrikx <<a href="mailto:john.hendrikx@gmail.com">john.hendrikx@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I couldn't find a discussion on openjdk, but for those interested (and <br>
to save others some searching) there is a JBS ticket:<br>
<br>
<a href="https://bugs.openjdk.org/browse/JDK-8025597" rel="noreferrer" target="_blank">https://bugs.openjdk.org/browse/JDK-8025597</a><br>
<br>
--John<br>
<br>
On 21/08/2023 14:37, Pavel Rappo wrote:<br>
> This is suggested every once in a while. I appreciate that openjdk mailing lists are not easily searchable, but with a bit of skill, you could find a few previous discussions on the topic.<br>
><br>
> This has also been discussed on concurrency-interest (at <a href="http://cs.oswego.edu" rel="noreferrer" target="_blank">cs.oswego.edu</a> <<a href="http://cs.oswego.edu/" rel="noreferrer" target="_blank">http://cs.oswego.edu/</a>>), a dedicated mailing list for concurrency in Java. Sadly, that list has been defunct for quite some time now.<br>
><br>
> -Pavel<br>
><br>
>> On 21 Aug 2023, at 13:18, Albert Attard <<a href="mailto:albertattard@gmail.com" target="_blank">albertattard@gmail.com</a>> wrote:<br>
>><br>
>> Hello.<br>
>><br>
>> I hope all is well.<br>
>><br>
>> Do you believe it is a bad idea to enrich the Lock interface with a set of default methods that safely release the lock once ready?<br>
>><br>
>> Consider the following (dangerous) example.<br>
>><br>
>> final Lock lock = new ReentrantLock ();<br>
>> lock.lock();<br>
>> /* Code that may throw an exception */<br>
>> lock.unlock();<br>
>><br>
>> This example will never release the lock if an exception is thrown, as the programmer didn’t wrap this up in a try/finally.<br>
>><br>
>> Adding a default method within the Lock interface, called withLock(Runnable) for example or any better name, would streamline this, as shown next.<br>
>><br>
>> default void withLock(final Runnable runnable) {<br>
>> requireNonNull(runnable, "Cannot run a null");<br>
>> lock();<br>
>> try {<br>
>> runnable.run();<br>
>> } finally {<br>
>> unlock();<br>
>> }<br>
>> }<br>
>><br>
>> The caller can now simply change the above example into the following, without having to worry about this.<br>
>><br>
>> final Lock lock = new ReentrantLock ();<br>
>> lock.withLock(() -> {<br>
>> /* Code that may throw an exception */<br>
>> });<br>
>><br>
>> We can have more variants of these default methods, as shown next.<br>
>><br>
>> default <T> T getWithLock(final Supplier<T> supplier) {<br>
>> requireNonNull(supplier, "The supplier cannot be null");<br>
>> lock();<br>
>> try {<br>
>> return supplier.get();<br>
>> } finally {<br>
>> unlock();<br>
>> }<br>
>> }<br>
>><br>
>> Any thoughts?<br>
>><br>
>> With kind regards,<br>
>> Albert Attard<br>
</blockquote></div>