src/share/classes/java/util/concurrent/ConcurrentHashMap.java

Print this page
rev 654 : 8009063: Improve reliability of ConcurrentHashMap
Reviewed-by: alanb, ahgross, omajid

  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/licenses/publicdomain
  34  */
  35 
  36 package java.util.concurrent;
  37 import java.util.concurrent.locks.*;
  38 import java.util.*;
  39 import java.io.Serializable;
  40 import java.io.IOException;
  41 import java.io.ObjectInputStream;
  42 import java.io.ObjectOutputStream;

  43 
  44 /**
  45  * A hash table supporting full concurrency of retrievals and
  46  * adjustable expected concurrency for updates. This class obeys the
  47  * same functional specification as {@link java.util.Hashtable}, and
  48  * includes versions of methods corresponding to each method of
  49  * <tt>Hashtable</tt>. However, even though all operations are
  50  * thread-safe, retrieval operations do <em>not</em> entail locking,
  51  * and there is <em>not</em> any support for locking the entire table
  52  * in a way that prevents all access.  This class is fully
  53  * interoperable with <tt>Hashtable</tt> in programs that rely on its
  54  * thread safety but not on its synchronization details.
  55  *
  56  * <p> Retrieval operations (including <tt>get</tt>) generally do not
  57  * block, so may overlap with update operations (including
  58  * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
  59  * of the most recently <em>completed</em> update operations holding
  60  * upon their onset.  For aggregate operations such as <tt>putAll</tt>
  61  * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
  62  * removal of only some entries.  Similarly, Iterators and


1430                         s.writeObject(e.key);
1431                         s.writeObject(e.value);
1432                     }
1433                 }
1434             } finally {
1435                 seg.unlock();
1436             }
1437         }
1438         s.writeObject(null);
1439         s.writeObject(null);
1440     }
1441 
1442     /**
1443      * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
1444      * stream (i.e., deserialize it).
1445      * @param s the stream
1446      */
1447     @SuppressWarnings("unchecked")
1448     private void readObject(java.io.ObjectInputStream s)
1449         throws IOException, ClassNotFoundException  {
1450         s.defaultReadObject();
















1451 
1452         // Re-initialize segments to be minimally sized, and let grow.
1453         int cap = MIN_SEGMENT_TABLE_CAPACITY;
1454         final Segment<K,V>[] segments = this.segments;
1455         for (int k = 0; k < segments.length; ++k) {
1456             Segment<K,V> seg = segments[k];
1457             if (seg != null) {
1458                 seg.threshold = (int)(cap * seg.loadFactor);
1459                 seg.table = (HashEntry<K,V>[]) new HashEntry[cap];
1460             }
1461         }
1462 
1463         // Read the keys and values, and put the mappings in the table
1464         for (;;) {
1465             K key = (K) s.readObject();
1466             V value = (V) s.readObject();
1467             if (key == null)
1468                 break;
1469             put(key, value);
1470         }
1471     }
1472 
1473     // Unsafe mechanics
1474     private static final sun.misc.Unsafe UNSAFE;
1475     private static final long SBASE;
1476     private static final int SSHIFT;
1477     private static final long TBASE;
1478     private static final int TSHIFT;



1479 
1480     static {
1481         int ss, ts;
1482         try {
1483             UNSAFE = sun.misc.Unsafe.getUnsafe();
1484             Class tc = HashEntry[].class;
1485             Class sc = Segment[].class;
1486             TBASE = UNSAFE.arrayBaseOffset(tc);
1487             SBASE = UNSAFE.arrayBaseOffset(sc);
1488             ts = UNSAFE.arrayIndexScale(tc);
1489             ss = UNSAFE.arrayIndexScale(sc);






1490         } catch (Exception e) {
1491             throw new Error(e);
1492         }
1493         if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0)
1494             throw new Error("data type scale not a power of two");
1495         SSHIFT = 31 - Integer.numberOfLeadingZeros(ss);
1496         TSHIFT = 31 - Integer.numberOfLeadingZeros(ts);
1497     }
1498 
1499 }

  23  */
  24 
  25 /*
  26  * This file is available under and governed by the GNU General Public
  27  * License version 2 only, as published by the Free Software Foundation.
  28  * However, the following notice accompanied the original version of this
  29  * file:
  30  *
  31  * Written by Doug Lea with assistance from members of JCP JSR-166
  32  * Expert Group and released to the public domain, as explained at
  33  * http://creativecommons.org/licenses/publicdomain
  34  */
  35 
  36 package java.util.concurrent;
  37 import java.util.concurrent.locks.*;
  38 import java.util.*;
  39 import java.io.Serializable;
  40 import java.io.IOException;
  41 import java.io.ObjectInputStream;
  42 import java.io.ObjectOutputStream;
  43 import java.io.ObjectStreamField;
  44 
  45 /**
  46  * A hash table supporting full concurrency of retrievals and
  47  * adjustable expected concurrency for updates. This class obeys the
  48  * same functional specification as {@link java.util.Hashtable}, and
  49  * includes versions of methods corresponding to each method of
  50  * <tt>Hashtable</tt>. However, even though all operations are
  51  * thread-safe, retrieval operations do <em>not</em> entail locking,
  52  * and there is <em>not</em> any support for locking the entire table
  53  * in a way that prevents all access.  This class is fully
  54  * interoperable with <tt>Hashtable</tt> in programs that rely on its
  55  * thread safety but not on its synchronization details.
  56  *
  57  * <p> Retrieval operations (including <tt>get</tt>) generally do not
  58  * block, so may overlap with update operations (including
  59  * <tt>put</tt> and <tt>remove</tt>). Retrievals reflect the results
  60  * of the most recently <em>completed</em> update operations holding
  61  * upon their onset.  For aggregate operations such as <tt>putAll</tt>
  62  * and <tt>clear</tt>, concurrent retrievals may reflect insertion or
  63  * removal of only some entries.  Similarly, Iterators and


1431                         s.writeObject(e.key);
1432                         s.writeObject(e.value);
1433                     }
1434                 }
1435             } finally {
1436                 seg.unlock();
1437             }
1438         }
1439         s.writeObject(null);
1440         s.writeObject(null);
1441     }
1442 
1443     /**
1444      * Reconstitute the <tt>ConcurrentHashMap</tt> instance from a
1445      * stream (i.e., deserialize it).
1446      * @param s the stream
1447      */
1448     @SuppressWarnings("unchecked")
1449     private void readObject(java.io.ObjectInputStream s)
1450         throws IOException, ClassNotFoundException  {
1451         // Don't call defaultReadObject()
1452         ObjectInputStream.GetField oisFields = s.readFields();
1453         final Segment<K,V>[] oisSegments = (Segment<K,V>[])oisFields.get("segments", null);
1454 
1455         final int ssize = oisSegments.length;
1456         if (ssize < 1 || ssize > MAX_SEGMENTS
1457             || (ssize & (ssize-1)) != 0 )  // ssize not power of two
1458             throw new java.io.InvalidObjectException("Bad number of segments:"
1459                                                      + ssize);
1460         int sshift = 0, ssizeTmp = ssize;
1461         while (ssizeTmp > 1) {
1462             ++sshift;
1463             ssizeTmp >>>= 1;
1464         }
1465         UNSAFE.putIntVolatile(this, SEGSHIFT_OFFSET, 32 - sshift);
1466         UNSAFE.putIntVolatile(this, SEGMASK_OFFSET, ssize - 1);
1467         UNSAFE.putObjectVolatile(this, SEGMENTS_OFFSET, oisSegments);
1468 
1469         // Re-initialize segments to be minimally sized, and let grow.
1470         int cap = MIN_SEGMENT_TABLE_CAPACITY;
1471         final Segment<K,V>[] segments = this.segments;
1472         for (int k = 0; k < segments.length; ++k) {
1473             Segment<K,V> seg = segments[k];
1474             if (seg != null) {
1475                 seg.threshold = (int)(cap * seg.loadFactor);
1476                 seg.table = (HashEntry<K,V>[]) new HashEntry[cap];
1477             }
1478         }
1479 
1480         // Read the keys and values, and put the mappings in the table
1481         for (;;) {
1482             K key = (K) s.readObject();
1483             V value = (V) s.readObject();
1484             if (key == null)
1485                 break;
1486             put(key, value);
1487         }
1488     }
1489 
1490     // Unsafe mechanics
1491     private static final sun.misc.Unsafe UNSAFE;
1492     private static final long SBASE;
1493     private static final int SSHIFT;
1494     private static final long TBASE;
1495     private static final int TSHIFT;
1496     private static final long SEGSHIFT_OFFSET;
1497     private static final long SEGMASK_OFFSET;
1498     private static final long SEGMENTS_OFFSET;
1499 
1500     static {
1501         int ss, ts;
1502         try {
1503             UNSAFE = sun.misc.Unsafe.getUnsafe();
1504             Class tc = HashEntry[].class;
1505             Class sc = Segment[].class;
1506             TBASE = UNSAFE.arrayBaseOffset(tc);
1507             SBASE = UNSAFE.arrayBaseOffset(sc);
1508             ts = UNSAFE.arrayIndexScale(tc);
1509             ss = UNSAFE.arrayIndexScale(sc);
1510             SEGSHIFT_OFFSET = UNSAFE.objectFieldOffset(
1511                 ConcurrentHashMap.class.getDeclaredField("segmentShift"));
1512             SEGMASK_OFFSET = UNSAFE.objectFieldOffset(
1513                 ConcurrentHashMap.class.getDeclaredField("segmentMask"));
1514             SEGMENTS_OFFSET = UNSAFE.objectFieldOffset(
1515                 ConcurrentHashMap.class.getDeclaredField("segments"));
1516         } catch (Exception e) {
1517             throw new Error(e);
1518         }
1519         if ((ss & (ss-1)) != 0 || (ts & (ts-1)) != 0)
1520             throw new Error("data type scale not a power of two");
1521         SSHIFT = 31 - Integer.numberOfLeadingZeros(ss);
1522         TSHIFT = 31 - Integer.numberOfLeadingZeros(ts);
1523     }
1524 
1525 }