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的size()方法,是如何计算ConcurrentHashMap的大小的。
下面一个阶段,应该会分析一下线程吧!毕竟线程在面试的时候,会占的比重较大。
上一篇: Java11新特性
下一篇: 机器学习小白修炼之路