Class NonBlockingIdentityHashMap<TypeK,​TypeV>

  • Type Parameters:
    TypeK - the type of keys maintained by this map
    TypeV - the type of mapped values
    All Implemented Interfaces:
    java.io.Serializable, java.lang.Cloneable, java.util.concurrent.ConcurrentMap<TypeK,​TypeV>, java.util.Map<TypeK,​TypeV>

    public class NonBlockingIdentityHashMap<TypeK,​TypeV>
    extends java.util.AbstractMap<TypeK,​TypeV>
    implements java.util.concurrent.ConcurrentMap<TypeK,​TypeV>, java.lang.Cloneable, java.io.Serializable
    A lock-free alternate implementation of ConcurrentHashMap with better scaling properties and generally lower costs to mutate the Map. It provides identical correctness properties as ConcurrentHashMap. All operations are non-blocking and multi-thread safe, including all update operations. NonBlockingHashMap scales substatially better than ConcurrentHashMap for high update rates, even with a large concurrency factor. Scaling is linear up to 768 CPUs on a 768-CPU Azul box, even with 100% updates or 100% reads or any fraction in-between. Linear scaling up to all cpus has been observed on a 32-way Sun US2 box, 32-way Sun Niagra box, 8-way Intel box and a 4-way Power box. This class obeys the same functional specification as Hashtable, and includes versions of methods corresponding to each method of Hashtable. However, even though all operations are thread-safe, operations do not entail locking and there is not any support for locking the entire table in a way that prevents all access. This class is fully interoperable with Hashtable in programs that rely on its thread safety but not on its synchronization details.

    Operations (including put) generally do not block, so may overlap with other update operations (including other puts and removes). Retrievals reflect the results of the most recently completed update operations holding upon their onset. For aggregate operations such as putAll, concurrent retrievals may reflect insertion or removal of only some entries. Similarly, Iterators and Enumerations return elements reflecting the state of the hash table at some point at or since the creation of the iterator/enumeration. They do not throw ConcurrentModificationException. However, iterators are designed to be used by only one thread at a time.

    Very full tables, or tables with high reprobe rates may trigger an internal resize operation to move into a larger table. Resizing is not terribly expensive, but it is not free either; during resize operations table throughput may drop somewhat. All threads that visit the table during a resize will 'help' the resizing but will still be allowed to complete their operation before the resize is finished (i.e., a simple 'get' operation on a million-entry table undergoing resizing will not need to block until the entire million entries are copied).

    This class and its views and iterators implement all of the optional methods of the Map and Iterator interfaces.

    Like Hashtable but unlike HashMap, this class does not allow null to be used as a key or value.

    Since:
    1.5
    See Also:
    Serialized Form
    • Constructor Summary

      Constructors 
      Constructor Description
      NonBlockingIdentityHashMap()
      Create a new NonBlockingHashMap with default minimum size (currently set to 8 K/V pairs or roughly 84 bytes on a standard 32-bit JVM).
      NonBlockingIdentityHashMap​(int initial_sz)
      Create a new NonBlockingHashMap with initial room for the given number of elements, thus avoiding internal resizing operations to reach an appropriate size.
    • Method Summary

      All Methods Static Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      private static boolean CAS_key​(java.lang.Object[] kvs, int idx, java.lang.Object old, java.lang.Object key)  
      private boolean CAS_kvs​(java.lang.Object[] oldkvs, java.lang.Object[] newkvs)  
      private static boolean CAS_val​(java.lang.Object[] kvs, int idx, java.lang.Object old, java.lang.Object val)  
      private static NonBlockingIdentityHashMap.CHM chm​(java.lang.Object[] kvs)  
      void clear()
      Removes all of the mappings from this map.
      java.lang.Object clone()
      Creates a shallow copy of this hashtable.
      boolean contains​(java.lang.Object val)
      Legacy method testing if some key maps into the specified value in this table.
      boolean containsKey​(java.lang.Object key)
      Tests if the key in the table using the equals method.
      boolean containsValue​(java.lang.Object val)
      Returns true if this Map maps one or more keys to the specified value.
      java.util.Enumeration<TypeV> elements()
      Returns an enumeration of the values in this table.
      java.util.Set<java.util.Map.Entry<TypeK,​TypeV>> entrySet()
      Returns a Set view of the mappings contained in this map.
      TypeV get​(java.lang.Object key)
      Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.
      private static java.lang.Object get_impl​(NonBlockingIdentityHashMap topmap, java.lang.Object[] kvs, java.lang.Object key)  
      private static int hash​(java.lang.Object key)  
      private static int[] hashes​(java.lang.Object[] kvs)  
      private java.lang.Object[] help_copy​(java.lang.Object[] helper)  
      protected void initialize()  
      private void initialize​(int initial_sz)  
      boolean isEmpty()
      Returns size() == 0.
      private static java.lang.Object key​(java.lang.Object[] kvs, int idx)  
      java.util.Enumeration<TypeK> keys()
      Returns an enumeration of the keys in this table.
      java.util.Set<TypeK> keySet()
      Returns a Set view of the keys contained in this map.
      private static int len​(java.lang.Object[] kvs)  
      void print()
      Verbose printout of table internals, useful for debugging.
      private void print​(java.lang.Object[] kvs)  
      private void print2​(java.lang.Object[] kvs)  
      TypeV put​(TypeK key, TypeV val)
      Maps the specified key to the specified value in the table.
      void putAll​(java.util.Map<? extends TypeK,​? extends TypeV> m)
      Copies all of the mappings from the specified map to this one, replacing any existing mappings.
      TypeV putIfAbsent​(TypeK key, TypeV val)
      Atomically, do a put(TypeK, TypeV) if-and-only-if the key is not mapped.
      private TypeV putIfMatch​(java.lang.Object key, java.lang.Object newVal, java.lang.Object oldVal)  
      private static java.lang.Object putIfMatch​(NonBlockingIdentityHashMap topmap, java.lang.Object[] kvs, java.lang.Object key, java.lang.Object putval, java.lang.Object expVal)  
      private static long rawIndex​(java.lang.Object[] ary, int idx)  
      private void readObject​(java.io.ObjectInputStream s)  
      protected void rehash()  
      TypeV remove​(java.lang.Object key)
      Removes the key (and its corresponding value) from this map.
      boolean remove​(java.lang.Object key, java.lang.Object val)
      Atomically do a remove(Object) if-and-only-if the key is mapped to a value which is equals to the given value.
      TypeV replace​(TypeK key, TypeV val)
      Atomically do a put(key,val) if-and-only-if the key is mapped to some value already.
      boolean replace​(TypeK key, TypeV oldValue, TypeV newValue)
      Atomically do a put(key,newValue) if-and-only-if the key is mapped a value which is equals to oldValue.
      private static int reprobe_limit​(int len)  
      long reprobes()
      Get and clear the current count of reprobes.
      int size()
      Returns the number of key-value mappings in this map.
      java.lang.String toString()
      Returns a string representation of this map.
      private static java.lang.Object val​(java.lang.Object[] kvs, int idx)  
      java.util.Collection<TypeV> values()
      Returns a Collection view of the values contained in this map.
      private void writeObject​(java.io.ObjectOutputStream s)  
      • Methods inherited from class java.util.AbstractMap

        equals, hashCode
      • Methods inherited from class java.lang.Object

        finalize, getClass, notify, notifyAll, wait, wait, wait
      • Methods inherited from interface java.util.concurrent.ConcurrentMap

        compute, computeIfAbsent, computeIfPresent, forEach, getOrDefault, merge, replaceAll
      • Methods inherited from interface java.util.Map

        equals, hashCode
    • Field Detail

      • _Obase

        private static final int _Obase
      • _Oscale

        private static final int _Oscale
      • _kvs_offset

        private static final long _kvs_offset
      • _kvs

        private transient java.lang.Object[] _kvs
      • _last_resize_milli

        private transient long _last_resize_milli
      • NO_MATCH_OLD

        private static final java.lang.Object NO_MATCH_OLD
      • MATCH_ANY

        private static final java.lang.Object MATCH_ANY
      • TOMBSTONE

        private static final java.lang.Object TOMBSTONE
    • Constructor Detail

      • NonBlockingIdentityHashMap

        public NonBlockingIdentityHashMap()
        Create a new NonBlockingHashMap with default minimum size (currently set to 8 K/V pairs or roughly 84 bytes on a standard 32-bit JVM).
      • NonBlockingIdentityHashMap

        public NonBlockingIdentityHashMap​(int initial_sz)
        Create a new NonBlockingHashMap with initial room for the given number of elements, thus avoiding internal resizing operations to reach an appropriate size. Large numbers here when used with a small count of elements will sacrifice space for a small amount of time gained. The initial size will be rounded up internally to the next larger power of 2.
    • Method Detail

      • rawIndex

        private static long rawIndex​(java.lang.Object[] ary,
                                     int idx)
      • CAS_kvs

        private final boolean CAS_kvs​(java.lang.Object[] oldkvs,
                                      java.lang.Object[] newkvs)
      • hash

        private static final int hash​(java.lang.Object key)
      • hashes

        private static final int[] hashes​(java.lang.Object[] kvs)
      • len

        private static final int len​(java.lang.Object[] kvs)
      • key

        private static final java.lang.Object key​(java.lang.Object[] kvs,
                                                  int idx)
      • val

        private static final java.lang.Object val​(java.lang.Object[] kvs,
                                                  int idx)
      • CAS_key

        private static final boolean CAS_key​(java.lang.Object[] kvs,
                                             int idx,
                                             java.lang.Object old,
                                             java.lang.Object key)
      • CAS_val

        private static final boolean CAS_val​(java.lang.Object[] kvs,
                                             int idx,
                                             java.lang.Object old,
                                             java.lang.Object val)
      • print

        public final void print()
        Verbose printout of table internals, useful for debugging.
      • print

        private final void print​(java.lang.Object[] kvs)
      • print2

        private final void print2​(java.lang.Object[] kvs)
      • reprobes

        public long reprobes()
        Get and clear the current count of reprobes. Reprobes happen on key collisions, and a high reprobe rate may indicate a poor hash function or weaknesses in the table resizing function.
        Returns:
        the count of reprobes since the last call to reprobes() or since the table was created.
      • reprobe_limit

        private static final int reprobe_limit​(int len)
      • initialize

        private final void initialize​(int initial_sz)
      • initialize

        protected final void initialize()
      • size

        public int size()
        Returns the number of key-value mappings in this map.
        Specified by:
        size in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        size in class java.util.AbstractMap<TypeK,​TypeV>
        Returns:
        the number of key-value mappings in this map
      • isEmpty

        public boolean isEmpty()
        Returns size() == 0.
        Specified by:
        isEmpty in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        isEmpty in class java.util.AbstractMap<TypeK,​TypeV>
        Returns:
        size() == 0
      • containsKey

        public boolean containsKey​(java.lang.Object key)
        Tests if the key in the table using the equals method.
        Specified by:
        containsKey in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        containsKey in class java.util.AbstractMap<TypeK,​TypeV>
        Returns:
        true if the key is in the table using the equals method
        Throws:
        java.lang.NullPointerException - if the specified key is null
      • contains

        public boolean contains​(java.lang.Object val)
        Legacy method testing if some key maps into the specified value in this table. This method is identical in functionality to containsValue(java.lang.Object), and exists solely to ensure full compatibility with class Hashtable, which supported this method prior to introduction of the Java Collections framework.
        Parameters:
        val - a value to search for
        Returns:
        true if this map maps one or more keys to the specified value
        Throws:
        java.lang.NullPointerException - if the specified value is null
      • put

        public TypeV put​(TypeK key,
                         TypeV val)
        Maps the specified key to the specified value in the table. Neither key nor value can be null.

        The value can be retrieved by calling get(java.lang.Object) with a key that is equal to the original key.

        Specified by:
        put in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        put in class java.util.AbstractMap<TypeK,​TypeV>
        Parameters:
        key - key with which the specified value is to be associated
        val - value to be associated with the specified key
        Returns:
        the previous value associated with key, or null if there was no mapping for key
        Throws:
        java.lang.NullPointerException - if the specified key or value is null
      • putIfAbsent

        public TypeV putIfAbsent​(TypeK key,
                                 TypeV val)
        Atomically, do a put(TypeK, TypeV) if-and-only-if the key is not mapped. Useful to ensure that only a single mapping for the key exists, even if many threads are trying to create the mapping in parallel.
        Specified by:
        putIfAbsent in interface java.util.concurrent.ConcurrentMap<TypeK,​TypeV>
        Specified by:
        putIfAbsent in interface java.util.Map<TypeK,​TypeV>
        Returns:
        the previous value associated with the specified key, or null if there was no mapping for the key
        Throws:
        java.lang.NullPointerException - if the specified key or value is null
      • remove

        public TypeV remove​(java.lang.Object key)
        Removes the key (and its corresponding value) from this map. This method does nothing if the key is not in the map.
        Specified by:
        remove in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        remove in class java.util.AbstractMap<TypeK,​TypeV>
        Returns:
        the previous value associated with key, or null if there was no mapping for key
        Throws:
        java.lang.NullPointerException - if the specified key is null
      • remove

        public boolean remove​(java.lang.Object key,
                              java.lang.Object val)
        Atomically do a remove(Object) if-and-only-if the key is mapped to a value which is equals to the given value.
        Specified by:
        remove in interface java.util.concurrent.ConcurrentMap<TypeK,​TypeV>
        Specified by:
        remove in interface java.util.Map<TypeK,​TypeV>
        Throws:
        java.lang.NullPointerException - if the specified key or value is null
      • replace

        public TypeV replace​(TypeK key,
                             TypeV val)
        Atomically do a put(key,val) if-and-only-if the key is mapped to some value already.
        Specified by:
        replace in interface java.util.concurrent.ConcurrentMap<TypeK,​TypeV>
        Specified by:
        replace in interface java.util.Map<TypeK,​TypeV>
        Throws:
        java.lang.NullPointerException - if the specified key or value is null
      • replace

        public boolean replace​(TypeK key,
                               TypeV oldValue,
                               TypeV newValue)
        Atomically do a put(key,newValue) if-and-only-if the key is mapped a value which is equals to oldValue.
        Specified by:
        replace in interface java.util.concurrent.ConcurrentMap<TypeK,​TypeV>
        Specified by:
        replace in interface java.util.Map<TypeK,​TypeV>
        Throws:
        java.lang.NullPointerException - if the specified key or value is null
      • putIfMatch

        private final TypeV putIfMatch​(java.lang.Object key,
                                       java.lang.Object newVal,
                                       java.lang.Object oldVal)
      • putAll

        public void putAll​(java.util.Map<? extends TypeK,​? extends TypeV> m)
        Copies all of the mappings from the specified map to this one, replacing any existing mappings.
        Specified by:
        putAll in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        putAll in class java.util.AbstractMap<TypeK,​TypeV>
        Parameters:
        m - mappings to be stored in this map
      • clear

        public void clear()
        Removes all of the mappings from this map.
        Specified by:
        clear in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        clear in class java.util.AbstractMap<TypeK,​TypeV>
      • containsValue

        public boolean containsValue​(java.lang.Object val)
        Returns true if this Map maps one or more keys to the specified value. Note: This method requires a full internal traversal of the hash table and is much slower than containsKey(java.lang.Object).
        Specified by:
        containsValue in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        containsValue in class java.util.AbstractMap<TypeK,​TypeV>
        Parameters:
        val - value whose presence in this map is to be tested
        Returns:
        true if this map maps one or more keys to the specified value
        Throws:
        java.lang.NullPointerException - if the specified value is null
      • rehash

        protected void rehash()
      • clone

        public java.lang.Object clone()
        Creates a shallow copy of this hashtable. All the structure of the hashtable itself is copied, but the keys and values are not cloned. This is a relatively expensive operation.
        Overrides:
        clone in class java.util.AbstractMap<TypeK,​TypeV>
        Returns:
        a clone of the hashtable.
      • toString

        public java.lang.String toString()
        Returns a string representation of this map. The string representation consists of a list of key-value mappings in the order returned by the map's entrySet view's iterator, enclosed in braces ("{}"). Adjacent mappings are separated by the characters ", " (comma and space). Each key-value mapping is rendered as the key followed by an equals sign ("=") followed by the associated value. Keys and values are converted to strings as by String.valueOf(Object).
        Overrides:
        toString in class java.util.AbstractMap<TypeK,​TypeV>
        Returns:
        a string representation of this map
      • get

        public TypeV get​(java.lang.Object key)
        Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key.

        More formally, if this map contains a mapping from a key k to a value v such that key.equals(k), then this method returns v; otherwise it returns null. (There can be at most one such mapping.)

        Specified by:
        get in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        get in class java.util.AbstractMap<TypeK,​TypeV>
        Throws:
        java.lang.NullPointerException - if the specified key is null
      • get_impl

        private static final java.lang.Object get_impl​(NonBlockingIdentityHashMap topmap,
                                                       java.lang.Object[] kvs,
                                                       java.lang.Object key)
      • putIfMatch

        private static final java.lang.Object putIfMatch​(NonBlockingIdentityHashMap topmap,
                                                         java.lang.Object[] kvs,
                                                         java.lang.Object key,
                                                         java.lang.Object putval,
                                                         java.lang.Object expVal)
      • help_copy

        private final java.lang.Object[] help_copy​(java.lang.Object[] helper)
      • elements

        public java.util.Enumeration<TypeV> elements()
        Returns an enumeration of the values in this table.
        Returns:
        an enumeration of the values in this table
        See Also:
        values()
      • values

        public java.util.Collection<TypeV> values()
        Returns a Collection view of the values contained in this map. The collection is backed by the map, so changes to the map are reflected in the collection, and vice-versa. The collection supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Collection.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

        The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

        Specified by:
        values in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        values in class java.util.AbstractMap<TypeK,​TypeV>
      • keys

        public java.util.Enumeration<TypeK> keys()
        Returns an enumeration of the keys in this table.
        Returns:
        an enumeration of the keys in this table
        See Also:
        keySet()
      • keySet

        public java.util.Set<TypeK> keySet()
        Returns a Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from this map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

        The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

        Specified by:
        keySet in interface java.util.Map<TypeK,​TypeV>
        Overrides:
        keySet in class java.util.AbstractMap<TypeK,​TypeV>
      • entrySet

        public java.util.Set<java.util.Map.Entry<TypeK,​TypeV>> entrySet()
        Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. The set supports element removal, which removes the corresponding mapping from the map, via the Iterator.remove, Set.remove, removeAll, retainAll, and clear operations. It does not support the add or addAll operations.

        The view's iterator is a "weakly consistent" iterator that will never throw ConcurrentModificationException, and guarantees to traverse elements as they existed upon construction of the iterator, and may (but is not guaranteed to) reflect any modifications subsequent to construction.

        Warning: the iterator associated with this Set requires the creation of Map.Entry objects with each iteration. The NonBlockingIdentityHashMap does not normally create or using Map.Entry objects so they will be created soley to support this iteration. Iterating using keySet() or values() will be more efficient.

        Specified by:
        entrySet in interface java.util.Map<TypeK,​TypeV>
        Specified by:
        entrySet in class java.util.AbstractMap<TypeK,​TypeV>
      • writeObject

        private void writeObject​(java.io.ObjectOutputStream s)
                          throws java.io.IOException
        Throws:
        java.io.IOException
      • readObject

        private void readObject​(java.io.ObjectInputStream s)
                         throws java.io.IOException,
                                java.lang.ClassNotFoundException
        Throws:
        java.io.IOException
        java.lang.ClassNotFoundException