根据Java并发实践,章11.4.3说:
锁分裂有时可以扩展到分区锁定在variablesized组独立的对象,在这种情况下它被称为锁条带化。 例如,的ConcurrentHashMap的实现使用的16个锁,其中的每一个守卫散列桶的1/16的阵列; 桶N由锁N模16保护。
我仍然有问题的理解和可视化的锁分离和水桶机制。 有人能很好的理解的话解释这:)
提前致谢。
根据Java并发实践,章11.4.3说:
锁分裂有时可以扩展到分区锁定在variablesized组独立的对象,在这种情况下它被称为锁条带化。 例如,的ConcurrentHashMap的实现使用的16个锁,其中的每一个守卫散列桶的1/16的阵列; 桶N由锁N模16保护。
我仍然有问题的理解和可视化的锁分离和水桶机制。 有人能很好的理解的话解释这:)
提前致谢。
散列映射构建的阵列,其中所述散列函数的对象映射到底层数组中的一个元素上。 假设底层阵列具有1024个元素 - 的ConcurrentHashMap实际上变成64个元素,例如,{0,63},{64,127}等。每个子阵列具有其自己的锁的16个不同的子阵列这个,所以修改{0,63}子阵列不会影响{64,127}子阵列 - ,而另一个线程写入到第二子阵列一个线程可以写入到第一子阵列。
在锁定之间的差Collections.synchronizedMap()
和一个ConcurrentHashMap
如下:
如果多个线程将访问Collections.synchronizedMap()
频繁,会有大量争用,因为每个方法是使用共享锁同步的(即,如果线程X调用一个方法Collections.synchronizedMap()
所有其他线程将是从调用的任何方法在阻塞Collections.synchronizedMap()
直到它从调用的方法)线程X回报。
甲ConcurrentHashMap
具有可变数目的锁(默认为16),每个保护在所述键的链段ConcurrentHashMap
。 因此,对于一个ConcurrentHashMap
与160键,每个键锁将防护罩10层的元件。 因此,在一个关键的操作方法( get
, put
, set
等)只锁定访问的密钥是在同一网段按键操作等方法。 例如,如果线程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();
}
这里的关键概念是“斗”。 而不是使用该全哈希表的全局锁,它使用一个小锁的每个桶。 这也是一个很好的类似于桶排序可提高排序的复杂性。