有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在处理并发哈希映射时必须使用锁

下面是我的一个类中的代码:

 class SomeClass {

   private Map<Integer, Integer> map = new ConcurrentHashMap<>();
   private volatile int counter = 0;
   final AtomicInteger sum = new AtomicInteger(0); // will be used in other classes/threads too
   private ReentrantLock l = new ReentrantLock();

   public void put(String some) {
    l.lock();
    try {
        int tmp = Integer.parseInt(some);
        map.put(counter++, tmp);
        sum.getAndAdd(tmp);
    } finally {
        l.unlock();
    }
   }

   public Double get() {
    l.lock();
    try {
        //... perform some map resizing operation ...
        // some calculations including sum field ...
    } finally {
        l.unlock();
    }
   }

}

您可以假设这个类将在并发环境中使用

问题是:你认为锁的必要性是什么?这段代码闻起来怎么样?:)


共 (1) 个答案

  1. # 1 楼答案

    让我们看看public void put(String some)中的操作

    1. map.put(counter++, tmp);
    2. sum.getAndAdd(tmp);

    现在让我们看一下各个部分

    1. counter是一个易变变量。因此,它只提供内存可见性,而不提供原子性。因为counter++是一个复合操作,所以需要一个锁来实现原子性

    2. map.put(key, value)是原子的,因为它是ConcurrentHashMap

    3. sum.getAndAdd(tmp)是原子的,因为它是AtomicInteger

    如您所见,除了counter++之外,其他所有操作都是原子操作。然而,您正试图通过组合所有这些操作来实现某些功能。要在功能级别实现原子性,需要一个锁。这将帮助您避免线程在各个原子操作之间交错时产生意外的副作用

    所以你需要一个锁,因为counter++不是原子的,你需要结合一些原子操作来实现一些功能(假设你希望它是原子的)