ConcurrentHashMap Поток безопасно? - PullRequest
2 голосов
/ 11 апреля 2020

Вот как я определил ConcurrentHashMap:

ConcurrentHashMap<Integer, ArrayList<Object>> all_payloads = new ConcurrentHashMap<Integer, ArrayList<Object>>();

Я понимаю, что там операция блокировки работает только при записи или удалении из ConcurrentHashMap, но эта блокировка распространяется на значения, которые являются типа ArrayList тоже?

Например:

for(int i = 0; i < all_payloads.get(0).size(); i++) {
        if(all_payloads.get(0).get(i).getBucketNumberCollector() == this.bucket_no) {
            currentPayload = all_payloads.get(0).remove(i);
            currentPayload.setCollector(collector);
            all_payloads.get(1).add(currentPayload);
            break;
        }
    }

В приведенном выше фрагменте я использую только метод get​(Object key) для изменения значения, связанного с этим ключом - который в этот случай имеет тип ArrayList.

Будет ли приведенный выше фрагмент безопасным для потоков? Если нет, то что можно сделать, чтобы сделать это так?

Ответы [ 2 ]

2 голосов
/ 11 апреля 2020

Даже если ArrayList был поточно-ориентированным (но это не так), у вас есть четыре разных all_payloads.get вызова в этом фрагменте, и даже если они индивидуально поточно-ориентированы, их комбинация не является (вызовы может быть чередоваться при наличии параллелизма).

0 голосов
/ 11 апреля 2020

Нет, это не так. ArrayList - это ArrayList, независимо от того, где вы его положили. Синхронизация ConcurrentHashMap распространяется только на операцию get, и с этого момента, если несколько потоков могут выполнять один и тот же фрагмент кода одновременно, вам потребуется дополнительный механизм для его защиты.

List<Object> myList = all_payloads.get(0);
synchronized (myList) {
    // code that uses myList
...