/** * Save the state of the <tt>ConcurrentHashMap</tt> instance to a stream (i.e., serialize it). * * @param s the stream * @serialData the key (Object) and value (Object) for each key-value mapping, followed by a null * pair. The key-value mappings are emitted in no particular order. */ private void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWriteObject(); for (int k = 0; k < segments.length; ++k) { Segment<V> seg = segments[k]; seg.lock(); try { HashEntry<V>[] tab = seg.table; for (int i = 0; i < tab.length; ++i) { for (HashEntry<V> e = tab[i]; e != null; e = e.next) { s.writeObject(e.key); s.writeObject(e.value); } } } finally { seg.unlock(); } } s.writeObject(null); s.writeObject(null); }
boolean replace(int key, int hash, V oldValue, V newValue) { lock(); try { HashEntry<V> e = getFirst(hash); while (e != null && (e.hash != hash || key != e.key)) e = e.next; boolean replaced = false; if (e != null && oldValue.equals(e.value)) { replaced = true; e.value = newValue; } return replaced; } finally { unlock(); } }
lock(); try { int c = count - 1;
segments[i].lock(); boolean found = false; try {
sum = 0; for (int i = 0; i < segments.length; ++i) segments[i].lock(); for (int i = 0; i < segments.length; ++i) sum += segments[i].count;
V put(int key, int hash, V value, boolean onlyIfAbsent) { lock(); try { int c = count; if (c++ > threshold) // ensure capacity rehash(); HashEntry<V>[] tab = table; int index = hash & (tab.length - 1); HashEntry<V> first = tab[index]; HashEntry<V> e = first; while (e != null && (e.hash != hash || key != e.key)) e = e.next; V oldValue; if (e != null) { oldValue = e.value; if (!onlyIfAbsent) e.value = value; } else { oldValue = null; ++modCount; tab[index] = new HashEntry<V>(key, hash, first, value); count = c; // write-volatile } return oldValue; } finally { unlock(); } }
V replace(int key, int hash, V newValue) { lock(); try { HashEntry<V> e = getFirst(hash); while (e != null && (e.hash != hash || key != e.key)) e = e.next; V oldValue = null; if (e != null) { oldValue = e.value; e.value = newValue; } return oldValue; } finally { unlock(); } }
void clear() { if (count != 0) { lock(); try { HashEntry<V>[] tab = table; for (int i = 0; i < tab.length; i++) tab[i] = null; ++modCount; count = 0; // write-volatile } finally { unlock(); } } } }
/** * Reads value field of an entry under lock. Called if value field ever appears to be null. This * is possible only if a compiler happens to reorder a HashEntry initialization with its table * assignment, which is legal under memory model but is not known to ever occur. */ V readValueUnderLock(HashEntry<V> e) { lock(); try { return e.value; } finally { unlock(); } }