Skip to content

Instantly share code, notes, and snippets.

@zouzanyan
Last active March 25, 2025 11:04
Show Gist options
  • Select an option

  • Save zouzanyan/025fb1de61af7b3e405e02c0ef24f881 to your computer and use it in GitHub Desktop.

Select an option

Save zouzanyan/025fb1de61af7b3e405e02c0ef24f881 to your computer and use it in GitHub Desktop.
基于cow思想用无锁实现的线程安全的hashmap
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