[
https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12915328#action_12915328
]
Alexander Apanasovich edited comment on LANG-609 at 9/28/10 12:28 AM:
----------------------------------------------------------------------
There is one more variant of the implementation, which should not have that
drawback described in class javadocs:
??The drawback is that the {...@link #initialize()} method can be called
multiple times which may be problematic if the creation of the managed object
is expensive. As a rule of thumb this initializer implementation is preferable
if there are not too many threads involved and the probability that multiple
threads access an uninitialized object is small. If there is high parallelism,
{...@link LazyInitializer} is more appropriate.??
{code}
/**
* Concurrent lazy initializer which guarantees concurrent access and
initialization during the first access.
* This implementation also guarantees that the factory method (initialize)
will be only invoked once.
*/
public abstract class AtomicInitializer<T> {
private final AtomicReference<AtomicInitializer<T>> factory = new
AtomicReference<AtomicInitializer<T>>();
private final AtomicReference<T> instance = new AtomicReference<T>();
/**
* Get (and initialize, if not initialized yet) the required object
*
* @return lazily initialized object
*/
public final T get() throws ConcurrentException {
T result;
while ((result = instance.get()) == null) {
if (factory.compareAndSet(null, this)) {
instance.compareAndSet(null, initialize());
}
}
return result;
}
/**
* Factory method, which is invoked once during first call to {...@link
#get()}
*
* @return new object
*/
protected abstract T initialize() throws ConcurrentException;
}
{code}
Sometimes the initialize method is expensive or dangerous to be called more
than once, so this implementation will guarantee single initialization and
concurrent access while having possibly a bit higher speed than
LazyInitializer, because there is no synchronization.
(changed private fields to final)
was (Author: apanasovich):
There is one more variant of the implementation, which should not have that
drawback described in class javadocs:
??The drawback is that the {...@link #initialize()} method can be called
multiple times which may be problematic if the creation of the managed object
is expensive. As a rule of thumb this initializer implementation is preferable
if there are not too many threads involved and the probability that multiple
threads access an uninitialized object is small. If there is high parallelism,
{...@link LazyInitializer} is more appropriate.??
{code}
/**
* Concurrent lazy initializer which guarantees concurrent access and
initialization during the first access.
* This implementation also guarantees that the factory method (initialize)
will be only invoked once.
*/
public abstract class AtomicInitializer<T> {
private AtomicReference<AtomicInitializer<T>> factory = new
AtomicReference<AtomicInitializer<T>>();
private AtomicReference<T> instance = new AtomicReference<T>();
/**
* Get (and initialize, if not initialized yet) the required object
*
* @return lazily initialized object
*/
public final T get() throws ConcurrentException {
T result;
while ((result = instance.get()) == null) {
if (factory.compareAndSet(null, this)) {
instance.compareAndSet(null, initialize());
}
}
return result;
}
/**
* Factory method, which is invoked once during first call to {...@link
#get()}
*
* @return new object
*/
protected abstract T initialize() throws ConcurrentException;
}
{code}
Sometimes the initialize method is expensive or dangerous to be called more
than once, so this implementation will guarantee single initialization and
concurrent access while having possibly a bit higher speed than
LazyInitializer, because there is no synchronization.
> Support lazy initialization using atomic variables
> --------------------------------------------------
>
> Key: LANG-609
> URL: https://issues.apache.org/jira/browse/LANG-609
> Project: Commons Lang
> Issue Type: New Feature
> Components: lang.concurrent.*
> Reporter: Oliver Heger
> Priority: Minor
> Fix For: 3.0
>
> Attachments: AtomicInitializer.patch
>
>
> In the new concurrent package there is already the {{LazyInitializer}} class
> implementing the double-check idiom for lazy initialization of instance
> fields. Another way to perform initialization lazily would be the usage of
> atomic variables. This solution would not need synchronization at all. If
> there is low contention (not many threads in parallel), it is more efficient
> than synchronized access. Its drawback is that the initialization may be done
> multiple times if multiple threads access the initializer almost at the same
> time (however, it can be guaranteed that always the same object created by
> the initializer is returned).
> This is a proposal to add an {{AtomicInitializer}} class as an alternative to
> {{LazyInitializer}} that operates on {{AtomicReference}} variables.
> In order to make the initializers smoothly exchangable, it would make sense
> for them to share a common interface. This interface could also be
> implemented by the {{BackgroundInitializer}} class.
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.