[concurrency-interest] syntax sugar for lazy instantiation

Jim Andreou jim.andreou at gmail.com
Tue Jun 23 17:08:42 EDT 2009


There is a typo inside the synchronized block, it should be obj == null.
All in all, it looks good, saves some boilerplate.

2009/6/24 Ashley Williams <ashpublic at mac.com>

> Included this so now we have:
> @ThreadSafe
> public abstract class LazyField<T> implements Callable<T> {
> private volatile T obj;
>
> public T get() {
> // use a local variable to save on multiple reads of a volatile
> T result = obj;
> if (result == null) {
> synchronized (this) {
> if (result == null) {
> result = call();
> obj = result;
> }
> }
> }
> return result;
> }
> }
>
> with usage example:
>
> private final LazyField<Logger> antLogger = new LazyField<Logger>() {
> public Logger call() throws Exception {
> return Logger.getLogger(Log4jListener.LOG_ANT);
> }
> };
>
> Looking a lot tidier now.
>
>
> On 23 Jun 2009, at 19:47, Jim Andreou wrote:
>
> An piece of advice from Josh Bloch:
>
> if (obj == null) {
>                     ....
>  }
>  return obj;
>
> It's better to store obj in a local field and use that for these two reads,
> this way you save a volatile read operation.
>
>
> I very much like Scala's implementation of this (though this is a language
> feature instead of a library): lazy val function = ..., and there, you got a
> nice version of the double checked locking idiom created for you :) (which
> also allows the lengthy computation to return just null, since it uses an
> extra bit to encode whether the field is initialized or not).
>
> Dimitris
>
> 2009/6/23 Ashley Williams <ashpublic at mac.com>
>
>> It seems to me that the only reason to use an intrinsic lock on a lazy
>> getter (stick a synchronized keyword
>> on the method signature) is convenience of syntax. Please correct me if I
>> am wrong.
>>
>> So is one idea to simplify lazy instantiation, feedback welcome if anybody
>> can improve on it. It's based
>> on the observation that double checked locking is mostly boilerplate
>> except for the line that creates
>> the instance and so I've factored it out into a callable interface.
>>
>> Admittedly the anonymous class makes for a more verbose constructor, but
>> at least the dcl logic is
>> now encapsulated. And if java had support for closures then the
>> readability problem would go away.
>>
>> So first the class:
>>
>> @ThreadSafe
>> public final class LazyField<T> {
>>  private volatile T obj;
>>  private final Callable<T> callable;
>>
>> public LazyField(Callable<T> callable) {
>>  this.callable = callable;
>>  }
>>
>>  public T get() {
>> if (obj == null) {
>>  synchronized (this) {
>>  if (obj == null) {
>>  obj = callable.call();
>>  }
>> }
>>  }
>>  return obj;
>>  }
>> }
>>
>> and here is an example usage:
>>
>> @ThreadSafe
>> public final class MyClass {
>>  private final LazyField<String> message;
>>
>> public MyClass() {
>>  this.message = new LazyField<String>(new Callable<String>() {
>>  public String call() throws Exception {
>>  return "hello world";
>>  }
>> });
>>  }
>>
>> public String getMessage() {
>>  return message.get();
>>  }
>> }
>>
>> - Ashley Williams
>>
>> _______________________________________________
>> Concurrency-interest mailing list
>> Concurrency-interest at cs.oswego.edu
>> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>>
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20090624/d6491ec4/attachment-0001.html>


More information about the Concurrency-interest mailing list