jdk源码——集合(ConcurrentHashMap)

     看这个集合的源码时,内心是拒绝的,六千多行的代码量,够我们看一段时间的。ConcurrentHashMap使线程安全的,底层是散列表+红黑树,线程安全不是在方法上使用synchronize关键字,使用了两种方式,第一是锁分段,第二是一个CAS算法。

    jdk1.8之前使用的是锁分段机制,jdk1.8之后,变为CAS算法。

   简单说一下,锁分段机制,嗯,意思就是这么个意思。每个段中都有一个散列表。每一个段都是一个segments,每个segments都是都一个锁。

 


       在jdk1.8之后使用的CAS算法效率更高,因为没有了上下文的切换,节省了时间。

       CAS(Compare and swap比较和交换)算法,是一种很有名无锁算法。是一种无所的非阻塞算法的实现

       CAS算法:包含了三个操作数,

                              需要读写的内存值V,预估的值A,替换的新值B

                              当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会有任何操作

       大概意思就是,我们要替换时,需要调用方法,compare(int A,int B),所以必须设置一个预估值,预估值,从何出来,会有一个方法提供内存值V,获得V值,将其传入到compare方法中,在这个方法中,比在此比较V 和A的值,如果相等,则可以替换。因为内存值没有改变,所以线程安全。

       这是一个模拟的CAS算法。意思就是这么个意思。

public class CompareSwapModel {
	
	public static void main(String[] args) {
		
		final Comswap comswap=new Comswap();
		
		for(int i=0;i<10;i++){
			
			new Thread(new Runnable() {
				
				@Override
				public void run() {
					
					int A=comswap.get();
					System.out.println(comswap.compareswapset(A, 9));
				}
			}).start();	
		}
	}
}
	
//当然CAS算法中并不是使用的是synchronized关键字,他是对硬件的调用,而我们模拟使用的synchronized关键字,是对模拟器的调用
	class Comswap{
		private int value ;//内存值
		
		public synchronized int get(){
			return value;
		}
		
		//比较
		public synchronized int compareswap(int expectedVlue ,int newValue){
			int oldavlaue=value;
			
			if(oldavlaue==expectedVlue){
				//如果两个相等
				this.value=newValue;
			}
			return oldavlaue;
		}
		
		//设置
		public synchronized boolean compareswapset(int expectedVlue ,int newValue){
			
			return expectedVlue==compareswap(expectedVlue,newValue);
		}
	}

       问题:CAS算法,是一个无锁算法,是不是其中就是没有锁?

           回答是,不是的,他依然使用了synchronize关键字,hash值相同的链表的头结点还是会synchronized上锁。


         还有一个关键字,volatile,volatile仅仅用来保证该变量对所有线程的可见性,但不保证原子性。

    可见性:在多线程的环境下:当这个变量修改时,所有的线程都会知道该变量被修改了,也就是所谓的“可见性”

    不保证原子性:修改变量(赋值)实质上是在JVM中分了好几步,而在这几步内(从装载变量到修改),它是不安全的

     其实这一篇,就是简单的介绍,我是没有能力将ConcurrentHashMap分析的多好。所以,大家还是尽量在网上多找一些资料,多看一些大牛写的分析看一下吧,我其实很多时候,也是在网上搜索的。。。

     算了,以后再写吧,我自己看源码,很多东西,都处于懵逼状态。嗯,没办法了。

    ---------未完待续,这一篇的更新时间,不确定,有可能几个星期以后,或者更长时间。。。。。

    不过。我在网上看了一篇文章,讲的很好,在这里附有链接,大家可以看一下。

   ConcurrentHashMap原理分析

    大家可以看一下,我就是看的这一篇,共同学习。面试的时候,我在网上看的,一个帖子,他说特面试的时候问到ConcurrentHashMap的size()方法,是如何计算ConcurrentHashMap的大小的。

  

    下面一个阶段,应该会分析一下线程吧!毕竟线程在面试的时候,会占的比重较大。

    

     

    

    


                
JDK7中的ConcurrentHashMap是Java中的线程安全的哈希表实现,它支持高并发的读写操作。下面是对其源码的简要介绍: 1. ConcurrentHashMap的内部结构: ConcurrentHashMap的内部结构由一个Segment数组和一个HashEntry数组组成。Segment是一种可重入锁,用于对HashEntry数组中的元素进行加锁操作。每个Segment维护了一个HashEntry数组的子集,不同的Segment之间可以并发地进行读写操作。 2. HashEntry的结构: HashEntry是ConcurrentHashMap中存储键值对的节点,它包含了键、值和一个指向下一个节点的引用。当多个键值对映射到同一个桶时,它们会形成一个链表。 3. ConcurrentHashMap的put操作: 当调用put方法向ConcurrentHashMap中插入键值对时,首先会根据键的哈希值找到对应的Segment,然后在该Segment中进行插入操作。如果插入的键已经存在,则会更新对应的值;如果插入的键不存在,则会创建一个新的节点并插入到链表的头部。 4. ConcurrentHashMap的get操作: 当调用get方法从ConcurrentHashMap中获取值时,首先会根据键的哈希值找到对应的Segment,然后在该Segment中进行查找操作。如果找到了对应的节点,则返回节点的值;如果没有找到,则返回null。 5. ConcurrentHashMap的扩容: 当ConcurrentHashMap中的元素数量达到一定阈值时,会触发扩容操作。扩容过程会创建一个新的Segment数组和HashEntry数组,并将原来的元素重新分配到新的数组中。在扩容过程中,读操作可以继续进行,而写操作会被阻塞。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值