博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
线程安全相关及ConcurrentHashMap总结
阅读量:5235 次
发布时间:2019-06-14

本文共 1191 字,大约阅读时间需要 3 分钟。

a. Volatile 关键字:对 Volatile 域的写入操作 happens-before 于每个后续对同一 Volatile 的读操作。

    并不保证线程安全。Volatile应用于多核系统的多线程应用中,因为每个cpu都有自己的缓存,并不实时更新到主内存。
    多线程环境下,a线程从主内存中读到的数据可能是更改前的,因为b线程更改的数据还在其他核的缓存区。
    Volatile声明的变量可以防止这一情况的发生,读操作必然是写操作写到主内存后的数据。
b.读写锁 - java.util.concurrent.locks.ReentrantReadWriteLock
    (1)readLock() , 进入条件:(a)没有其他线程的写锁 (b) 没有写请求或者有写请求,但调用线程和持有锁的线程是同一个
    (2)writeLock() ,进入条件:(a)没有其他线程的读锁 (b) 没有其他线程的写锁
    简单地理解,读锁是共享锁,写锁是排它锁。
c.提高并发量的线程安全工具-ConcurrentHashMap
    (1)穿插 - HashMap的数据结构
    (a)大体结构:散列表(数组) + 链表(1.8后是链表或红黑树)
    (b)根据key算hash,hashcode是根据地址进行高低位混合运算。根据hashcode的值作为下标插入桶中(就是插入数组中),如果已经有元素,
    组装成为链表,新加入的元素作为表头,元素数量大于8个时,组装成红黑树(1.8+)。
    (c)散列表的大小都是2^n,当75%的位置都有元素时,会触发resize,会把散列表扩容一倍,所有元素重排。
    (2)ConcurrentHashMap的数据结构
    (a)先分为16 个 Segment 对象的数组(默认),每个Segment各自维护自己的散列表。
    运行锁机制的是Segment对象(继承于 ReentrantLock 类)。理想状况下允许16个线程并发。
    (b)put操作。
        <1>先算hash,根据hash找到对应的Segment,再在Segment里面加锁进行put操作。
        <2>因为加锁在Segment里面,理想情况下,可以支持 16 个线程执行并发写操作。
    (c)remove操作。
        remove操作不删除原有元素,而是组建一条新的链表到待删除元素的下一元素,当然新的链表是没有待删除元素的。
        旧的链表是没有头的,故新的get操作不会进入旧链表。
    (d)get操作相关。
        get可以在put和remove时正常地读而没有异常产生(因为remove不删除原有元素)。
        如果get到null值,说明发生resize,加锁再读一次(ConcurrentHashMap不允许null值)。

 

2018.12.08

转载于:https://www.cnblogs.com/fu-feng/p/11173670.html

你可能感兴趣的文章
(转载)关于Linux C函数strtok的使用要点
查看>>
C#委托、事件剖析(上)
查看>>
P1631 序列合并
查看>>
Luogu_4886 快递员
查看>>
通过段调优顾问帮助解决行链接问题
查看>>
内存优化文章链接
查看>>
ext4.0 代理 的使用
查看>>
数据检查约束类型和语法
查看>>
AngularJS实战之路由ui-view
查看>>
使用jQuery+huandlebars防止编码注入攻击
查看>>
C#的托管与非托管大难点
查看>>
[转]HTTPS简谈
查看>>
(图片)jsp上传图片,进行缩放处理
查看>>
集合类List,set,Map 的遍历方法,用法和区别
查看>>
HDU-2577-How to Type
查看>>
java日志框架之logback——布局详细说明书地址
查看>>
Java Selenium (十二) 操作弹出窗口 & 智能等待页面加载完成 & 处理 Iframe 中的元素...
查看>>
Scala入门系列(十):函数式编程之集合操作
查看>>
pulseaudio的交叉编译
查看>>
win7 环境安装Python + IDE(vs2010)开发
查看>>