[concurrency-interest] syntax sugar for lazy instantiation

Ashley Williams ashpublic at mac.com
Tue Jun 23 17:03:17 EDT 2009


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/20090623/133ac2a3/attachment.html>


More information about the Concurrency-interest mailing list