1
votes

mon code est-il sûr pour les threads? comment atteindre la sécurité des threads dans ce cas sinon?

On m'a posé une question lors d'une interview. Que faire Si je veux stocker des valeurs dans la carte comme ceci:

t1.get("key_1").put("value_4");    
t2.get("key_1").put("value_5");

Ici, si nous supposons que la clé et la valeur sont dans une chaîne, nous devrions prendre la carte comme ceci ..

XXX

Ensuite, on m'a demandé: que faire si vous voulez assurer la sécurité des threads? Ensuite, j'ai dit que nous pouvions prendre ConcurrentHashMap à cet effet .. ils ont dit ok ..

Ensuite, ils ont demandé quelle valeur je veux dire La liste est threadsafe? Ex.

Map<String,List<String>> m1 = new HashMap();

Ici, supposons que les deux threads t1 et t2 fonctionnent en parallèle. Donc, si cette List je veux dire la valeur dans ConcurrentHashMap est Thread-Safe? Si oui, comment? et si non, comment y parvenir ??


4 commentaires

Cela dépend de la mise en œuvre de List.


Les valeurs stockées dans un ConcurrentHashMap ne sont ni plus ni moins thread-safe que les valeurs en dehors de la carte.


@AndyTurner, pouvez-vous expliquer en détail? Je ne t'ai pas compris, désolé pour ça.


Les opérations que vous effectuez sur la carte seront thread-safe, c'est-à-dire get () et put () et containsKey (). Mais une fois que vous avez récupéré la valeur [qui est une liste dans votre cas], la sécurité des threads pour les modifications relatives à ces éléments de liste dépendra entièrement de l'implémentation de l'objet liste [ou de tout autre objet java].


3 Réponses :


1
votes

ConcurrentHashMap est la structure de données Thread Safe. Si vous utilisez List (qui n'est pas thread-safe) dans la valeur de ConcurrentHashMap alors la List n'est pas thread-safe car deux threads peuvent sécuriser la référence de la liste et la modifier ultérieurement en parallèle.

ConcurrentHashMap est un thread safe signifie que ses opérations comme put et putAll etc. sont thread-safe. Cela ne signifie pas la structure de données qui que vous utilisez comme valeur deviennent également Thread safe.

Comment y parvenir?

  • Utilisez Thread Safe List comme CopyOnWriteArrayList comme valeur dans votre ConcurrentHashMap .
  • Personnalisez la Liste et rendez toutes leurs méthodes synchronisées .
  • Convertissez la List non thread-safe en List Thread safe en transmettant Collections.synchronizedList (non-Thread safelist) .

0 commentaires

0
votes

J'ai dit que nous pouvions utiliser ConcurrentHashMap à cette fin .. ils ont dit ok ..

Peut-être que ça va, peut-être pas. Cela dépend de l'existence ou non d'une relation spéciale entre key_1 et key_2.

Supposons qu'un thread stocke une nouvelle valeur pour key_1, puis juste avant de pouvoir stocker une valeur associée pour key_2, sa tranche de temps se termine. Un autre thread examine ensuite les valeurs de key_1 et key_2 pendant que le premier thread est suspendu. Il voit la nouvelle valeur de key_1, mais il voit la ancienne valeur de key_2.

Est-il important à ce stade que le premier thread n'ait été qu'à mi-chemin de la mise à jour des deux clés?

Le branchement d'un ConcurrentHashMap garantira que la structure de données de la carte elle-même ne fera rien de drôle ou de mal dans une application multi-thread, mais si l'application dépend de ces deux clés toujours mises à jour ensemble, alors vous allez toujours avoir besoin d'une sorte de verrouillage explicite pour vous assurer qu'ils sont toujours mis à jour ensemble.


0 commentaires

0
votes

Il est facile de tester via le code:

        Map<String,List<String>> m1 = new ConcurrentHashMap();
        m1.put("s1", new ArrayList<>());
        CountDownLatch countDownLatch = new CountDownLatch(2);
        new Thread(() -> {
            int i = 500;
            while (i-- > 0) {
                m1.get("s1").add(i + "");
            }
            countDownLatch.countDown();
        }).start();

        new Thread(() -> {
            int i = 500;
            while (i-- > 0) {
                m1.get("s1").add(i + "");
            }
            countDownLatch.countDown();
        }).start();
        countDownLatch.await();
        // may be < 1000,
        // or ArrayIndexOutOfBoundsException happens before this line of code executes
        System.out.println(m1.get("s1").size()); 


0 commentaires