How do I implement a Clustered Singleton?

The following code example demonstrates how to implement a clustered singleton.

import com.tangosol.net.CacheFactory;
import com.tangosol.net.NamedCache;
 
/**
* Singleton using cache to back it. (Commented out code is from a single-JVM
* traditional singleton pattern. New code supports stateless session EJB
* singleton pattern.)
*
* @author cp 2003.01.13
*/
public class Singleton
    {
    // ----- constructors ---------------------------------------------------
 
    /**
    * Allow multiple instances to be instantiated; they will all share the
    * same state.
    */
    public /*private*/ Singleton()
        {
        }
 
 
    // ----- properties -----------------------------------------------------
 
    /**
    * Accessor for Name property.
    *
    * @return  the current name value
    */
    public String getName()
        {
        // return m_sName;
        return (String) m_cache.get("Name");
        }
 
    /**
    * Mutator for Name property.
    *
    * @param sName  the new name value
    */
    public void setName(String sName)
        {
        // m_sName = sName;
        m_cache.put("Name", sName);
        }
 
    // more complex properties, such as hashtables, can be serialized into
    // the cache, but it is usually preferable to instantiate a separate
    // cache to replace complex objects such as a hashtable; instead of
    // exposing the hashtable as a property (i.e. "public Hashtable
    // getHashtable()"), it is better to expose the accessors and mutators
    // for the objects that the hashtable manages (i.e. "public Account[]
    // getAccounts()" and "public void addAccount(Account)" and "public void
    // removeAccount(Account)").
 
 
    // ----- concurrency ----------------------------------------------------
 
    /**
    * Lock the object in the cluster, and wait until the lock is available.
    * <p>
    * This is the cluster equivalent to the MONITORENTER Java opcode that
    * results from the Java synchronized keyword.
    * <p>
    * The non-clustered code would look like:
    * <pre><code>
    *   synchronized (Singleton.INSTANCE) {
    *     ...
    *   }
    * </code></pre>
    * <p>
    * The clustered equivalent would look like:
    * <pre><code>
    *   Singleton.INSTANCE.lock();
    *   try {
    *     ...
    *   } finally {
    *     Singleton.INSTANCE.unlock();
    *   }
    * </code></pre>
    */
    public void lock()
        {
        m_cache.lock("monitor", -1L);
        }
 
    /**
    * Unlock the object in the cluster.
    * <p>
    * This is the cluster equivalent to the MONITOREXIT Java opcode that
    * results from the Java synchronized keyword.
    */
    public void unlock()
        {
        m_cache.unlock("monitor");
        }
 
 
    // ----- data members ---------------------------------------------------
 
    /**
    * Singleton instance. (In a clustered environment, this will not be the
    * only instance.)
    */
    public static final Singleton INSTANCE = new Singleton();
 
    /**
    * Field storage for the Name property.
    */
    // private String m_sName;
 
    /**
    * Cache storage for all properties.
    * Note, this uses the default replicated 'cache-mapping' that ships with the Coherence distribution.
    */
    private final NamedCache m_cache = CacheFactory.getCache("repl-" + 
            getClass().getName(), getClass().getClassLoader());
    }