W javadoc dla ConcurrentHashMap jest następujący:
Operacje pobierania (w tym get) na ogół nie blokują się, więc mogą nakładać się na operacje aktualizacji (w tym operacje przesyłania i usuwania). Pobieranie odzwierciedla wyniki ostatnio zakończonych operacji aktualizacji, które miały miejsce w momencie ich rozpoczęcia. W przypadku operacji zagregowanych, takich jak putAll i clear, jednoczesne pobieranie może odzwierciedlać wstawianie lub usuwanie tylko niektórych wpisów. Podobnie Iteratory i Enumerations zwracają elementy odzwierciedlające stan tabeli skrótów w pewnym momencie lub od momentu utworzenia iteratora / wyliczenia. Nie zgłaszają wyjątku ConcurrentModificationException. Jednak iteratory są zaprojektowane do używania tylko przez jeden wątek naraz.
Co to znaczy? Co się stanie, jeśli spróbuję iterować mapę z dwoma wątkami w tym samym czasie? Co się stanie, jeśli wstawię lub usunę wartość z mapy podczas jej iteracji?
ConcurrentModificationException
czasu na iteracjęConcurrentHashMap
, dlaczego?Możesz użyć tej klasy do przetestowania dwóch wątków uzyskujących dostęp i jednego mutującego współdzieloną instancję
ConcurrentHashMap
:Żaden wyjątek nie zostanie odrzucony.
Udostępnianie tego samego iteratora między wątkami akcesorów może prowadzić do zakleszczenia:
Gdy tylko zaczniesz udostępniać to samo
Iterator<Map.Entry<String, String>>
między wątkami akcesorów i mutatorówjava.lang.IllegalStateException
, zaczną pojawiać się s.źródło
Oznacza to, że nie powinieneś udostępniać obiektu iteratora między wieloma wątkami. Tworzenie wielu iteratorów i używanie ich jednocześnie w oddzielnych wątkach jest w porządku.
źródło
To może dać ci dobry wgląd
Odnośnie tego:
Oznacza to, że używanie iteratorów generowanych przez ConcurrentHashMap w dwóch wątkach jest bezpieczne, może to spowodować nieoczekiwany rezultat w aplikacji.
źródło
Oznacza to, że nie powinieneś próbować używać tego samego iteratora w dwóch wątkach. Jeśli masz dwa wątki, które wymagają iteracji po kluczach, wartościach lub wpisach, każdy z nich powinien utworzyć i używać własnych iteratorów.
Nie jest do końca jasne, co by się stało, gdybyś złamał tę zasadę. Możesz po prostu uzyskać mylące zachowanie, w taki sam sposób, jak robisz to, jeśli (na przykład) dwa wątki próbują czytać ze standardowego wejścia bez synchronizacji. Możesz również uzyskać zachowanie niegwintowane.
Ale jeśli dwa wątki używały różnych iteratorów, powinno być dobrze.
To osobna kwestia, ale sekcja javadoc, którą zacytowałeś, odpowiednio ją rozwiązuje. Zasadniczo iteratory są bezpieczne dla wątków, ale nie jest zdefiniowane, czy efekty wszelkich jednoczesnych wstawień, aktualizacji lub usunięcia będą odzwierciedlone w sekwencji obiektów zwracanych przez iterator. W praktyce prawdopodobnie zależy to od tego, gdzie na mapie występują aktualizacje.
źródło