`

并发集合 ConcurrentHash

阅读更多

Synchronized Collections

--同步集合 包括Vector 和 Hashtable,以及由 Collections.synchronizedXxx 工厂方法生成的同步包装类。


需要使用synchronized 关键字隐式加锁。iterator不支持并发修改。

 

Concurrent Collections

--并发集合

 

 

ConcurrentHashMap

 

并发HashMap内部的主角是segment数组,默认大小是16--并发级别,即支持16个并发。这是Lock Stripping锁分离理论的实践。

final Segment<K, V>[] segments;

final int segmentMask;
final int segmentShift;
 

构造并发HashMap时,创建segment数组。

while (ssize < concurrencyLevel) {
	++sshift;
	ssize <<= 1;
}
segmentShift = 32 - sshift;
segmentMask = ssize - 1;
this.segments = Segment.newArray(ssize);
 

数据结构: Map-Segment-HashEntry

 

Segement继承了可重入锁,extends ReentrantLock。

它只有一个含有两个参数的构造子:int initialCapacity, float loadFactor。

for (int i = 0; i < this.segments.length; ++i)
			this.segments[i] = new C_Segment<K, V>(cap, loadFactor);
if (initialCapacity > MAXIMUM_CAPACITY)
			initialCapacity = MAXIMUM_CAPACITY;
		int c = initialCapacity / ssize;
		if (c * ssize < initialCapacity)
			++c;
		int cap = 1;
		while (cap < c)
			cap <<= 1;

 

hash代表segment数组的指针。put的第一步是选择合适的segment。

public V putIfAbsent(K key, V value) {
	if (value == null)
		throw new NullPointerException();
	int hash = hash(key.hashCode());
	return segmentFor(hash).put(key, hash, value, true);
}

 

HashEntry是个单项链表中的一个节点,切next为final,不可修改。segment内部的table既是单项链表的数组。

put动作,需要对segment使用可重入锁。由此可以看出,put没有锁整个Map,锁粒度大大降低。

	V put(K key, int hash, V value, boolean onlyIfAbsent) {
		lock();
		try {
			int c = count;
			if (c++ > threshold) // ensure capacity
				rehash();
			HashEntry<K, V>[] tab = table;
			int index = hash & (tab.length - 1);
			HashEntry<K, V> first = tab[index];
			HashEntry<K, V> e = first;
			while (e != null && (e.hash != hash || !key.equals(e.key)))
				e = e.next;

			V oldValue;
			if (e != null) {
				oldValue = e.value;
				if (!onlyIfAbsent)
					e.value = value;
			} else {
				oldValue = null;
				++modCount;
				tab[index] = new HashEntry<K, V>(key, hash, first, value);
				count = c; // write-volatile
			}
			return oldValue;
		} finally {
			unlock();
		}
	}

 

读取数据,基本无需锁。

V get(Object key, int hash) {
	if (count != 0) { // read-volatile
		HashEntry<K, V> e = getFirst(hash);
		while (e != null) {
			if (e.hash == hash && key.equals(e.key)) {
				V v = e.value;
				if (v != null)
					return v;
				return readValueUnderLock(e); // recheck
			}
			e = e.next;
		}
	}
	return null;
}

删除动作需要对segment加锁。因为HashEntry的next是final的,因此,无法修改,只能新建一组单项列表,其中不含那个被删除的倒霉蛋。HashEntry<K, V> newFirst = e.next;

V remove(Object key, int hash, Object value) {
	lock();
	try {
		int c = count - 1;
		HashEntry<K, V>[] tab = table;
		int index = hash & (tab.length - 1);
		HashEntry<K, V> first = tab[index];
		HashEntry<K, V> e = first;
		while (e != null && (e.hash != hash || !key.equals(e.key)))
			e = e.next;

		V oldValue = null;
		if (e != null) {
			V v = e.value;
			if (value == null || value.equals(v)) {
				oldValue = v;
				// All entries following removed node can stay
				// in list, but all preceding ones need to be
				// cloned.
				++modCount;
				HashEntry<K, V> newFirst = e.next;
				for (HashEntry<K, V> p = first; p != e; p = p.next)
					newFirst = new HashEntry<K, V>(p.key, p.hash, newFirst, p.value);
				tab[index] = newFirst;
				count = c; // write-volatile
			}
		}
		return oldValue;
	} finally {
		unlock();
	}
}

 

 

 

ConcurrentSkipListMap,ConcurrentSkipListSet

 

分享到:
评论

相关推荐

    java并发集合

    在Java编程中,"java并发集合"是一个关键领域,它涉及到多线程环境下如何有效地管理和操作数据集合。Java提供了一系列的并发集合类,使得在并发环境中实现高效且线程安全的数据处理成为可能。这些集合主要存在于`...

    动态加载DLL,并发集合

    下面将详细介绍动态加载DLL的过程以及并发集合的相关知识。 首先,动态加载DLL的基础在于LoadLibrary和GetProcAddress这两个API函数。LoadLibrary用于在运行时加载指定路径的DLL文件,返回一个模块句柄,这个句柄...

    C#并发集合的简单方法.pdf

    C#并发集合是.NET Framework 4.0引入的一种强大的编程工具,旨在简化多线程环境下的数据访问和同步。并发集合是为了解决在多个线程同时访问共享数据时可能出现的问题,如脏读、脏写等问题。它们提供了一种线程安全的...

    多线程并发集合资料.zip

    在Java编程中,多线程并发集合是程序员在开发高并发应用时必须掌握的重要概念。这些集合类的设计目的是为了在多线程环境下提供高效、安全的数据共享,避免数据竞争和死锁等问题。以下是对给定文件中涉及知识点的详细...

    线程池和并发集合含源码

    线程池和并发集合含源码

    icnc, C 的Intel(R) 并发集合.zip

    icnc, C 的Intel(R) 并发集合 C 的 Intel(R) 并发集合无疼痛的并行性CnC主页在这里: https://icnc.github.io先决条件Linux*或者 Windows* ( iOS*应该有效,但还没有进行测试)TBB ( 英特尔( R

    java并非编程,合集(各种锁、并发集合、障碍器、线程同步).zip

    Java并发编程是Java开发中的重要领域,涉及到多线程、同步机制、锁的实现以及并发集合等关键概念。本合集深入探讨了这些主题,帮助开发者理解和掌握在Java环境中高效处理并发问题的技巧。 首先,我们要理解“锁”在...

    JVM_多线程高并发_集合框架_数据库 BAT面试金典常见80问.pdf

    《JVM_多线程高并发_集合框架_数据库 BAT面试金典常见80问.pdf》这份资料聚焦于Java开发人员在面试中可能遇到的重要问题,涵盖了JVM、多线程高并发、集合框架和数据库等多个核心领域。以下是对这些知识点的详细说明...

    java并发编程艺术

    并发集合是Java并发编程中的重要组成部分,如`ConcurrentHashMap`, `CopyOnWriteArrayList`, `ConcurrentLinkedQueue`等,它们设计为线程安全,能够在并发环境中高效地工作。书中的章节可能会详细解释这些集合的设计...

    java 并发编程的艺术pdf清晰完整版 源码

    Java语言提供了丰富的并发工具和API,如线程、守护线程、线程池、同步机制(synchronized、wait/notify)、并发集合(ConcurrentHashMap、CopyOnWriteArrayList等)以及并发框架(ExecutorService、Future、Callable...

    Loadrunner的并发用户数和集合点分析

    Loadrunner的并发用户数和集合点分析 Loadrunner的并发用户数和集合点分析

    高并发公开课集合

    高并发 , 限流 ,Java高并发, tomcat8结构与讲解等等

    java并发编程2

    以上知识点覆盖了Java并发编程的主要方面,包括线程管理、同步机制、并发工具、设计模式、并发集合以及并发编程的最佳实践等,是理解和掌握Java并发编程的关键。在实际开发中,理解和熟练运用这些知识可以编写出高效...

    Java 并发编程实战.pdf

    随着章节的深入,作者可能会更深入地讲解Java提供的并发工具,例如锁、原子变量、线程池、以及并发集合等高级特性。 在深入理解这些并发工具的基础上,读者可以学习到如何安全地共享数据,避免多线程之间的数据竞争...

    Java理论与实践:并发集合类

    本文介绍了在Java类库中出现的第一个关联的集合类是Hashtable,它是JDK 1.0的一部分。Hashtable提供了一种易于使用的、线程安全的、关联的map功能,这当然也是方便的。然而,线程安全性是凭代价换来的―― Hashtable...

    java虚拟机并发编程.pdf

    3. **并发集合**:Java并发集合库提供了一组线程安全的数据结构,如ConcurrentHashMap、CopyOnWriteArrayList等,这些集合能够在多线程环境下保持高效性能。 4. **原子操作与CAS**:Atomic类库中的原子变量支持无锁...

    Java并发编程常识-梁飞.rar

    总之,《Java并发编程常识》PPT涵盖了从基础概念到高级技术的广泛内容,包括线程管理、同步机制、并发集合、并发工具以及并发问题的解决。对于希望提升并发编程技能的Java开发者来说,这是一份不可多得的学习资料。

    探讨LoadRunner的并发用户和集合点

    近来跟踪一个项目,发现同事们在执行性能测试时,比较热衷于使用集合点,从概念上认为要得到并发用户就必须设置集合点,认为在执行一个压力测试脚本时,设置了集合点才算是有效的并发用户,没有设置结合点  近来...

Global site tag (gtag.js) - Google Analytics