尝试更新 Multimap 值时需要锁定键

问题描述 投票:0回答:1

我们有一个使用 Hazelcast Multimap 的用例。我们为集合中的每个元素的每个键生成一个线程。例如,如果 key1 有 10 个值,那么我们将生成 10 个线程,每个线程对应集合中的 10 个元素。

每个线程都尝试以并发方式更新它正在使用的元素。我的问题:

每次线程必须更新元素时,我都需要锁定 key1 吗?

我们有一个现有的系统,当我们必须使用任何键的集合更新任何元素时,我们会锁定 Multimap 键。由于某种原因,当值集合的大小为 30+ 时,我间歇性地遇到一个问题,即某个线程未释放键上的锁,并且后续线程持续等待很长时间(30+ 秒)锁。因此,如果一开始就能安全地摆脱锁定,那就太好了。

multithreading locking hazelcast multimap
1个回答
0
投票

这取决于您想做什么。例如,这段代码是线程安全的。

 MultiMap<Integer, Integer> multiMap = hazelcastClientInstance.getMultiMap(MULTI_MAP_NAME);

final int numThreads = 1000;
CountDownLatch latch = new CountDownLatch(numThreads);

for (int index = 0; index < numThreads; index++) {
  final int value = index;
  new Thread(() -> {
    multiMap.put(KEY, value);
    latch.countDown();
  }).start();
}
latch.await();

因为对数据结构的操作是由hazelcast上的单个线程执行的。有多少客户端线程发布操作并不重要

但是这段代码不是线程安全的。因为如文档中所述

同时改变给定 Collection 的结果是 未定义。

MultiMap<Integer, Integer> multiMap = hazelcastClientInstance.getMultiMap(MULTI_MAP_NAME);
multiMap.clear();
multiMap.put(KEY, 0);

final int numThreads = 1000;
CountDownLatch latch = new CountDownLatch(numThreads);

for (int index = 0; index < numThreads; index++) {
  new Thread(() -> {
    TreeSet<Integer> integerSet = new TreeSet<>(multiMap.get(KEY));
    // The clients are working on the collection without a lock
    Integer first = integerSet.first();
    LOGGER.info("first is {}", first);
    Set<Integer> collection = Set.of(first + 1);
    try {
      multiMap.putAllAsync(KEY, collection).toCompletableFuture().get();
    } catch (Exception ignored) {
  }
  latch.countDown();
  }).start();
}
latch.await();

总而言之,如果操作发布键+值,那么它是线程安全的。 如果操作是发布密钥+集合,则操作可能需要在密钥上使用锁

© www.soinside.com 2019 - 2024. All rights reserved.