• JDK源码分析(二)—— ConcurrentHashMap


    一、概述

    ConcurrentHashMap是Java5中新增加的一个线程安全的Map集合,可以用来替代HashTable。

    锁分段技术
    原理:将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一个段数据的时候,其他段的数据也能被其他线程访问。

    理解Java存储模型(JMM)的Happens-Before规则

    一个例子

    
    public class Test1 {
        private int a=1, b=2;
    
        public void foo(){  // 线程1 
            a=3;
            b=4;
        }
    
        public int getA(){ // 线程2
            return a;
        }    
        public int getB(){ // 线程2
            return b;
        }
    }
    
    

    当线程1执行foo方法的时候,线程2访问getA和getB会得到什么样的结果?

    A:a=1, b=2  // 都未改变
    B:a=3, b=4  // 都改变了
    C:a=3, b=2  //  a改变了,b未改变
    D:a=1, b=4  //  b改变了,a未改变
    

    多线程之间内存可见性(Visibility)顺序不一致的问题。有两种可能会造成上面的D选项。

    • Java编译器的重排序
    • 假设代码有两条语句,代码顺序是语句1先于语句2执行;那么只要语句2不依赖于语句1的结果,打乱它们的顺序对最终的结果没有影响的话,那么真正交给CPU去执行时,他们的顺序可以是没有限制的。可以允许语句2先于语句1被CPU执行,和代码中的顺序不一致。
    • 从线程工作内存写回主存时顺序无法保证

    JMM中一个重要问题就是:如何让多线程之间,对象的状态对于各线程的“可视性”是顺序一致的。它的解决方式就是 Happens-before 规则:

    JMM为所有程序内部动作定义了一个偏序关系,叫做happens-before。要想保证执行动作B的线程看到动作A的结果(无论A和B是否发生在同一个线程中),A和B之间就必须满足happens-before关系。

    后续分析ConcurrenHashMap时也会看到使用到锁(ReentrantLock),Volatile,final等手段来保证happens-before规则的。

    使用锁方式实现“Happens-before”是最简单,容易理解的。

    二、源码

    
    public class ConcurrentHashMap<K,V> extends AbstractMap<K,V>
        implements ConcurrentMap<K,V>, Serializable {
    
        static class Segment<K,V> extends ReentrantLock implements Serializable {
            private static final long serialVersionUID = 2249069246763182397L;
            final float loadFactor;
            Segment(float lf) { this.loadFactor = lf; }
        }
    
    }
    
    
  • 相关阅读:
    android之Fragment(官网资料翻译)
    Java获取当前时间的年月日方法
    Android Fragment Base
    Java JNI初探
    PHP 初学之登录查询小case
    PHP 初学
    tomcat:run和tomcat7:run的区别,以及Apache Tomcat Maven Plugin 相关
    Intellij IDEA:maven的本地仓库问题
    Java 构造方法的执行过程(猜测)
    PHP wamp server问题
  • 原文地址:https://www.cnblogs.com/fonxian/p/10037558.html
Copyright © 2020-2023  润新知