You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Oliver Heger (JIRA)" <ji...@apache.org> on 2010/03/16 22:32:27 UTC

[jira] Created: (LANG-609) Support lazy initialization using atomic variables

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


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.


[jira] Issue Comment Edited: (LANG-609) Support lazy initialization using atomic variables

Posted by "Alexander Apanasovich (JIRA)" <ji...@apache.org>.
    [ 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.


[jira] Commented: (LANG-609) Support lazy initialization using atomic variables

Posted by "Sebb (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12915334#action_12915334 ] 

Sebb commented on LANG-609:
---------------------------

I think the private fields "factory" and "instance" need to be made final to ensure safe publication between threads.

> 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.


[jira] Updated: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oliver Heger updated LANG-609:
------------------------------

    Attachment: AtomicInitializer.patch

The patch contains an implementation of the AtomicInitializer class. A new interface {{ConcurrentInitializer}} was introduced which is now implemented by all initializer classes. Also, an abstract base class for testing initializer implementations was added.

> 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.


[jira] Updated: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oliver Heger updated LANG-609:
------------------------------

    Attachment: AtomicInitializer.patch

New patch which also implements the proposed {{initialize()}} methods in {{ConcurrentUtils}}.

> 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.


[jira] Updated: (LANG-609) Support lazy initialization using atomic variables

Posted by "Henri Yandell (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Henri Yandell updated LANG-609:
-------------------------------

    Fix Version/s: 3.0

> 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
>
>
> 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.


[jira] Reopened: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oliver Heger reopened LANG-609:
-------------------------------


Reopening as there is some new discussion about this issue.

> 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.


[jira] Commented: (LANG-609) Support lazy initialization using atomic variables

Posted by "Henri Yandell (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12846469#action_12846469 ] 

Henri Yandell commented on LANG-609:
------------------------------------

Sounds good.

> 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
>
>
> 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.


[jira] Issue Comment Edited: (LANG-609) Support lazy initialization using atomic variables

Posted by "Alexander Apanasovich (JIRA)" <ji...@apache.org>.
    [ 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:37 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.set(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 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)
  
> 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.


[jira] Closed: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oliver Heger closed LANG-609.
-----------------------------

    Resolution: Fixed

A new AtomicSafeInitializer class was comitted in revision 1006174.

> 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.


[jira] Commented: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12917205#action_12917205 ] 

Oliver Heger commented on LANG-609:
-----------------------------------

Maybe there is room for all of these variants?

{{AtomicInitializer}} as it is now may be appropriate for use cases where multiple invocations of the {{initialize()}} method are not an issue. In such scenarios it is the most efficient variant.

The code proposed here could be added as a new class, say {{AtomicSafeInitializer}}. It has a bit more overhead, but guarantees the one-time initialization.

I am not sure how this {{AtomicSafeInitializer}} compares to the {{LazyInitializer}} implementation which is based on volatile variables and synchronization. I assume it will be more efficient under low or moderate load. If there are many thread trying to initialize the object concurrently, the synchronization approach might be preferrable. But this certainly depends on multiple factors, and users should do benchmarks in their concrete environment before they take a decision.

So would you agree to add this code as a new {{AtomicSafeInitializer}} class? Other preferences for the name?

> 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.


[jira] Commented: (LANG-609) Support lazy initialization using atomic variables

Posted by "Alexander Apanasovich (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12915328#action_12915328 ] 

Alexander Apanasovich commented on LANG-609:
--------------------------------------------

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.


[jira] Commented: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
    [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12847820#action_12847820 ] 

Oliver Heger commented on LANG-609:
-----------------------------------

The {{get()}} method in the {{ConcurrentInitializer}} interface now throws a {{ConcurrentException}}. This is a checked exception and forces client code to always catch and handle the exception.

LANG-610 proposes a new {{ConcurrentRuntimeException}} class which is an unchecked exception. It would be nice if the checked exception could automatically be transformed into the unchecked exception. To achieve this we could add convenience methods for the handling of initializers to {{ConcurrentUtils}}, e.g.:

{code}
public static <T> T initialize(ConcurrentInitializer<T> initializer) throws ConcurrentException;

public static <T> T initializeUnchecked(ConcurrentInitializer<T> initializer);
{code}

These methods could also be null-safe. The first variant would simply invoke the passed in {{ConcurrentInitializer}}. The second one would catch a {{ConcurrentException}} and transform it to a {{ConcurrentRuntimeException}}.

> 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.


[jira] Updated: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oliver Heger updated LANG-609:
------------------------------

    Attachment:     (was: AtomicInitializer.patch)

> 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.


[jira] Resolved: (LANG-609) Support lazy initialization using atomic variables

Posted by "Oliver Heger (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/LANG-609?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Oliver Heger resolved LANG-609.
-------------------------------

    Resolution: Fixed

Patch applied in revision 929189.

> 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.