需要简单的解释“锁分离”如何与ConcurrentHashMap的工作原理(Need simple

2019-08-31 18:46发布

根据Java并发实践,章11.4.3说:

锁分裂有时可以扩展到分区锁定在variablesized组独立的对象,在这种情况下它被称为锁条带化。 例如,的ConcurrentHashMap的实现使用的16个锁,其中的每一个守卫散列桶的1/16的阵列; 桶N由锁N模16保护。

我仍然有问题的理解和可视化的锁分离和水桶机制。 有人能很好的理解的话解释这:)

提前致谢。

Answer 1:

散列映射构建的阵列,其中所述散列函数的对象映射到底层数组中的一个元素上。 假设底层阵列具有1024个元素 - 的ConcurrentHashMap实际上变成64个元素,例如,{0,63},{64,127}等。每个子阵列具有其自己的锁的16个不同的子阵列这个,所以修改{0,63}子阵列不会影响{64,127}子阵列 - ,而另一个线程写入到第二子阵列一个线程可以写入到第一子阵列。



Answer 2:

在锁定之间的差Collections.synchronizedMap()和一个ConcurrentHashMap如下:

如果多个线程将访问Collections.synchronizedMap()频繁,会有大量争用,因为每个方法是使用共享锁同步的(即,如果线程X调用一个方法Collections.synchronizedMap()所有其他线程将是从调用的任何方法在阻塞Collections.synchronizedMap()直到它从调用的方法)线程X回报。

ConcurrentHashMap具有可变数目的锁(默认为16),每个保护在所述键的链段ConcurrentHashMap 。 因此,对于一个ConcurrentHashMap与160键,每个键锁将防护罩10层的元件。 因此,在一个关键的操作方法( getputset等)只锁定访问的密钥是在同一网段按键操作等方法。 例如,如果线程X调用put(0, someObject)然后线程ÿ调用put(10, someOtherObject)这些电话可以同时执行,线程Y不必等待线程X从返回put(0, someObject) 。 一个示例在以下提供。

另外,某些方法,如size()isEmpty()没有在所有受保护。 虽然这允许更大的并发性,这意味着它们不是强一致(它们不会反映在同时改变状态)。

public static void main(String[] args) {
  ConcurrentHashMap<Integer, Object> map = new ConcurrentHashMap<>(160);

  new Thread(new Runnable() {
    @Override
    public void run() {
      map.put(0, "guarded by one lock");
    }
  }.start();

  new Thread(new Runnable() {
    @Override
    public void run() {
      map.put(10, "guarded by another lock");
    }
  }.start();

  new Thread(new Runnable() {
    @Override
    public void run() {
      // could print 0, 1, or 2
      System.out.println(map.count());
    }
  }.start();
}


Answer 3:

这里的关键概念是“斗”。 而不是使用该全哈希表的全局锁,它使用一个小锁的每个桶。 这也是一个很好的类似于桶排序可提高排序的复杂性。



文章来源: Need simple explanation how “lock striping” works with ConcurrentHashMap