Maison  >  Article  >  Java  >  Quels sont les moyens d’implémenter la sécurité des threads pour Map en Java ?

Quels sont les moyens d’implémenter la sécurité des threads pour Map en Java ?

王林
王林avant
2023-04-19 19:52:041769parcourir

Méthode 1. Utiliser Hashtable

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

C'est la première chose à laquelle tout le monde pense, alors pourquoi est-il thread-safe ? Jetez ensuite un œil à son code source. Nous pouvons voir que nos méthodes couramment utilisées telles que put, get, containKey, etc. sont toutes synchrones, elles sont donc thread-safe

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;
    }

Le principe d'implémentation est d'utiliser synchronisé sur l'ajout. , supprimer, modifier et vérifier les méthodes Mécanisme de verrouillage, dans un environnement multithread, qu'il s'agisse de lire ou de modifier des données, un seul thread peut exécuter la méthode de synchronisation en même temps, car la table entière est verrouillée. Par conséquent, plus il y a de threads, plus la concurrence pour la carte est intense et plus l'efficacité est faible.

Méthode 2. Utiliser Collections.synchronizedMap(new Hashtable())

Le principe d'implémentation consiste à utiliser la méthode statique dans la classe d'outils pour regrouper la table de hachage entrante dans une table de hachage synchronisée, c'est-à-dire ajouter, supprimer, modifier et méthodes de vérification. Le mécanisme synchronisé est implémenté de la même manière que Hashtable et a une efficacité similaire. Il n'est pas recommandé de l'utiliser.

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

Ce qui suit est le code source du 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();}
        }
        ......
    }

Méthode 3. Utilisez ConcurrentHashMap

Le principe d'implémentation est que Hashtable verrouille la table entière, tandis que ConcurrentHashMap segmente la table, initialement en 16 segments, chaque segment a un Lorsque plusieurs threads accèdent différents segments, les verrous obtenus sont différents, ils sont donc accessibles en parallèle. L'efficacité est bien supérieure à celle de Hashtable, il est donc recommandé de l'utiliser.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer