Last active
March 25, 2025 11:04
-
-
Save zouzanyan/025fb1de61af7b3e405e02c0ef24f881 to your computer and use it in GitHub Desktop.
基于cow思想用无锁实现的线程安全的hashmap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| public class CopyOnWriteHashMap<K, V> implements Map<K, V>, Cloneable { | |
| private volatile Map<K, V> internalMap = new HashMap<>(); | |
| private static final Unsafe UNSAFE; | |
| private static final long INTERNAL_MAP_OFFSET; | |
| static { | |
| try { | |
| Field theUnsafeField = Unsafe.class.getDeclaredField("theUnsafe"); | |
| theUnsafeField.setAccessible(true); | |
| UNSAFE = (Unsafe) theUnsafeField.get(null); | |
| INTERNAL_MAP_OFFSET = UNSAFE.objectFieldOffset(CopyOnWriteHashMap.class.getDeclaredField("internalMap")); | |
| } catch (NoSuchFieldException | IllegalAccessException e) { | |
| throw new Error(e); | |
| } | |
| } | |
| public CopyOnWriteHashMap() { | |
| } | |
| public CopyOnWriteHashMap(Map<? extends K, ? extends V> m) { | |
| internalMap = new HashMap<>(m); | |
| } | |
| @Override | |
| public int size() { | |
| return internalMap.size(); | |
| } | |
| @Override | |
| public boolean isEmpty() { | |
| return internalMap.isEmpty(); | |
| } | |
| @Override | |
| public boolean containsKey(Object key) { | |
| return internalMap.containsKey(key); | |
| } | |
| @Override | |
| public boolean containsValue(Object value) { | |
| return internalMap.containsValue(value); | |
| } | |
| @Override | |
| public V get(Object key) { | |
| return internalMap.get(key); | |
| } | |
| @Override | |
| public V put(K key, V value) { | |
| Map<K, V> prevMap; | |
| Map<K, V> newMap; | |
| V oldValue; | |
| while (true){ | |
| prevMap = internalMap; | |
| // copy | |
| newMap = new HashMap<>(prevMap); | |
| // on write | |
| oldValue = newMap.put(key, value); | |
| // compare and swap | |
| if (UNSAFE.compareAndSwapObject(this, INTERNAL_MAP_OFFSET, prevMap, newMap)){ | |
| return oldValue; | |
| } | |
| } | |
| } | |
| @Override | |
| public V remove(Object key) { | |
| Map<K, V> prevMap; | |
| Map<K, V> newMap; | |
| V oldValue; | |
| while (true){ | |
| prevMap = internalMap; | |
| if (!prevMap.containsKey(key)) { | |
| return null; | |
| } | |
| newMap = new HashMap<>(prevMap); | |
| oldValue = newMap.remove(key); | |
| if (UNSAFE.compareAndSwapObject(this, INTERNAL_MAP_OFFSET, prevMap, newMap)){ | |
| return oldValue; | |
| } | |
| } | |
| } | |
| @Override | |
| public void putAll(Map<? extends K, ? extends V> m) { | |
| Map<K, V> prevMap; | |
| Map<K, V> newMap; | |
| while (true){ | |
| prevMap = internalMap; | |
| newMap = new HashMap<>(prevMap); | |
| newMap.putAll(m); | |
| if (UNSAFE.compareAndSwapObject(this, INTERNAL_MAP_OFFSET, prevMap, newMap)){ | |
| return; | |
| } | |
| } | |
| } | |
| @Override | |
| public void clear() { | |
| Map<K, V> prevMap = internalMap; | |
| if (prevMap.isEmpty()) { | |
| return; | |
| } | |
| while (!UNSAFE.compareAndSwapObject(this, INTERNAL_MAP_OFFSET, prevMap, new HashMap<>())) { | |
| ; | |
| } | |
| } | |
| @Override | |
| public Set<K> keySet() { | |
| return Collections.unmodifiableSet(internalMap.keySet()); | |
| } | |
| @Override | |
| public Collection<V> values() { | |
| return Collections.unmodifiableCollection(internalMap.values()); | |
| } | |
| @Override | |
| public Set<Entry<K, V>> entrySet() { | |
| return Collections.unmodifiableSet(internalMap.entrySet()); | |
| } | |
| @Override | |
| public boolean equals(Object o) { | |
| if (o == this) { | |
| return true; | |
| } | |
| if (!(o instanceof Map)) { | |
| return false; | |
| } | |
| return internalMap.equals(o); | |
| } | |
| @Override | |
| public int hashCode() { | |
| return internalMap.hashCode(); | |
| } | |
| @Override | |
| public String toString() { | |
| return internalMap.toString(); | |
| } | |
| @Override | |
| public CopyOnWriteHashMap<K, V> clone() { | |
| try { | |
| CopyOnWriteHashMap<K, V> cloned = (CopyOnWriteHashMap<K, V>) super.clone(); | |
| cloned.internalMap = new HashMap<>(this.internalMap); | |
| return cloned; | |
| } catch (CloneNotSupportedException e) { | |
| throw new AssertionError(e); | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment