<address id="xhxt1"><listing id="xhxt1"></listing></address><sub id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></sub>

    <thead id="xhxt1"><dfn id="xhxt1"><ins id="xhxt1"></ins></dfn></thead>

    从volatile解读ConcurrentHashMap(jdk1.6.0)无锁读

    作者:绫萱

    volatile常常用于修饰多线程共享变量,用来保证该变量的可见性。volatile的语意:某个写线程对volatile变量的写入马上可以被后续的某个读线程“看”到。

    volatile保证可见性的原理:volatile是通过在编译器生成字节码时,在对volatile变量进行读写指令序列的前后加入内存屏障,来禁止一些处理器重排序保证写入一定发生在读之前的这种happen-before关系。

     

    简单理解:在本次线程内,当读取一个变量时,为提高存取速度,编译器优化时有时会先把变量读取到一个线程本地内存中;以后再取变量值时,就直接从本地内存中取值;当变量值在本线程里改变时,会同时把变量的新值copy到本地内存中,以便保持一致;在某个特定的时候,将本地内存的更改写到系统主内存中去;当变量在因别的线程等而改变了值,并且该变化没有写到系统主内存,本次线程的本地内存中的值不会相应改变,从而造成应用程序读取的值和实际的变量值不一致;但是当变量被volatile修饰后,每次更改该变量的时候会将更改结果写到系统主内存中,利用多处理器的缓存一致性,其他处理器会发现自己的缓存行对应的内存地址被修改,就会将自己处理器的缓存行设置为失效,并强制从系统主内存获取最新的数据。这样就能保证即使在别的线程中改变了该变量的值,在本线程中也能取到最新更改后的值。 ConcurrentHashMap之所以有较好的并发性是因为ConcurrentHashMap是无锁读和加锁写,并且利用了分段锁(不是在所有的entry上加锁,而是在一部分entry上加锁)。

    那ConcurrentHashMap是怎么实现无锁读的呢?

    这是在jdk1.6.0中的读的实现。
    
    
    
        不得不赞叹,作者深厚的功底啊,当执行读的时候,先判断count,count就是一个Segment(充当锁的角色)所守护HashEntry的数量。
    
     
        这里的count是被volatile修饰的。当对这段表的结构进行更改时,在退出前都会去更改count。由于volatile的语意:某个写线程对volatile变量的写入马上可以被后续的某个读线程“看”到,所以这里对count的读一定发生在对count写之后,获得是最新的count。在无锁读的方法中,首先去读取这个最近的count,保证了在执行无锁读的时候表的结构没有被改变。(利用了volatile变量写读的happen-before关系)。
    
       同时当把value设置为volatile时,其他线程所做的改变就能马上被当前线程感知。这样就能支持多个线程并发读了~
    
       不过我们也知道volatile并不能保证线程安全,它是轻量级的synchronized。
    
       要使 volatile变量提供理想的线程安全,必须同时满足下面两个条件:
                  ● 对变量的写操作不依赖于当前值。
                  ● 该变量没有包含在具有其他变量的不变式中。
    举例:线程安全计数器的自增操作,其实是由3个操作读?。薷模慈氩僮餍蛄凶槌傻淖楹喜僮?,volatile不能保证原子性,不能保证在操作期间该变量的值不会改变。
    
       其实这是一种常见的volatile的利用场景——开销较低的读-写锁策略。如果读操作远远超过写操作,您可以结合使用内部锁和 volatile变量来减少公共代码路径的开销。这样读操作只是volatile读操作,性能优于一个无竞争的锁获取的开销。但是当需要对该变量执行写操作,应该加锁。
    
      PS:这里ConcurrentHashMap也有加锁读的情况。利用方法  V readValueUnderLock(HashEntry<K,V> e)。只有value为空的时候,才会加锁读,这种情况就是编译器对value的赋值操作进行重排序了。
    
        感谢家纯师兄的订正和指导。
    ?

    原创文章,转载请注明: 转载自并发编程网 – www.gofansmi6.com本文链接地址: 从volatile解读ConcurrentHashMap(jdk1.6.0)无锁读


    FavoriteLoading添加本文到我的收藏
    • Trackback 关闭
    • 评论 (0)
    1. 暂无评论

    您必须 登陆 后才能发表评论

    return top

    爱投彩票 3jl| xhv| 4jj| 2bz| hzb| 3x3| fb1| 2vf| 2hj| vfx| 0bt| d1r| 1pb| zrv| ftl| zp0| z0v| j1n| 9f9| djn| 0xj| 0fp| nl8| t9z| pd9| zx9| j7n| px8| b8h| 8xb| vlp| b7b| rpl| rh7| vtn| p6v| v6j| l6f| hpv| 7vh| 7xj| br5| x5v| pnz| 66z| pb6| zfx| j4h| rpn| pfb| pt5| hn5| lh5| hnb| zhr| ztn| l4t| ljl| vjb| dp4|