>Java >java지도 시간 >Java에서 Map에 대한 스레드 안전성을 구현하는 방법은 무엇입니까?

Java에서 Map에 대한 스레드 안전성을 구현하는 방법은 무엇입니까?

王林
王林앞으로
2023-04-19 19:52:041865검색

방법 1. Hashtable 사용

Map<String,Object> hashtable=new Hashtable<String,Object>();

이것이 모두가 가장 먼저 생각하는 것인데 왜 스레드로부터 안전할까요? 그런 다음 소스 코드를 살펴보면 put, get, containKey 등과 같이 일반적으로 사용되는 메서드가 모두 동기식이므로 스레드로부터 안전합니다

public synchronized boolean containsKey(Object key) {
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return true;
            }
        }
        return false;
    }

 public synchronized V get(Object key) {
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        for (Entry<?,?> e = tab[index] ; e != null ; e = e.next) {
            if ((e.hash == hash) && e.key.equals(key)) {
                return (V)e.value;
            }
        }
        return null;
    }
     public synchronized V put(K key, V value) {
        // Make sure the value is not null
        if (value == null) {
            throw new NullPointerException();
        }

        // Makes sure the key is not already in the hashtable.
        Entry<?,?> tab[] = table;
        int hash = key.hashCode();
        int index = (hash & 0x7FFFFFFF) % tab.length;
        @SuppressWarnings("unchecked")
        Entry<K,V> entry = (Entry<K,V>)tab[index];
        for(; entry != null ; entry = entry.next) {
            if ((entry.hash == hash) && entry.key.equals(key)) {
                V old = entry.value;
                entry.value = value;
                return old;
            }
        }

        addEntry(hash, key, value, index);
        return null;
    }

구현 원칙은 추가 시 동기화를 사용하는 것입니다. 잠금 메커니즘은 멀티 스레드 환경에서 데이터를 읽거나 수정하는 경우 전체 테이블이 잠겨 있기 때문에 하나의 스레드만 동시에 동기화 메서드를 실행할 수 있습니다. 따라서 스레드가 많을수록 맵을 두고 경쟁이 치열해지고 효율성이 떨어지므로 권장하지 않습니다.

방법 2. Collections.synchronizedMap(new Hashtable()) 사용

구현 원리는 도구 클래스의 정적 메서드를 사용하여 들어오는 Hashtable을 동기화된 테이블로 패키징하는 것입니다. 동기화 메커니즘은 Hashtable과 유사한 방식으로 구현되며 유사한 효율성을 가지므로 사용하지 않는 것이 좋습니다.

Map map = Collections.synchronizedMap(new Hashtable());

다음은 JDK 소스 코드입니다

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
}
private static class SynchronizedMap<K,V>
        implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;
 
        private final Map<K,V> m;     // Backing Map
        final Object      mutex;        // Object on which to synchronize
 
        SynchronizedMap(Map<K,V> m) {
            this.m = Objects.requireNonNull(m);
            mutex = this;
        }
 
        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }
 
        public int size() {
            synchronized (mutex) {return m.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized (mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized (mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
        }
 
        public V put(K key, V value) {
            synchronized (mutex) {return m.put(key, value);}
        }
        public V remove(Object key) {
            synchronized (mutex) {return m.remove(key);}
        }
        public void putAll(Map<? extends K, ? extends V> map) {
            synchronized (mutex) {m.putAll(map);}
        }
        public void clear() {
            synchronized (mutex) {m.clear();}
        }
        ......
    }

방법 3. ConcurrentHashMap 사용

구현 원리는 Hashtable이 전체 테이블을 잠그는 반면 ConcurrentHashMap은 테이블을 처음에는 16개의 세그먼트로 분할하고 각 세그먼트는 여러 스레드에 액세스할 때 세그먼트가 다르면 획득한 잠금도 다르기 때문에 병렬로 액세스할 수 있습니다. Hashtable에 비해 효율성이 훨씬 높으므로 사용을 권장합니다.

위 내용은 Java에서 Map에 대한 스레드 안전성을 구현하는 방법은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제