集合,ArrayList,LinkedList,HashMap,LinkedHashMap,ConcurremtHashMap分别的总结,volatile 关键字的使用

1    集合
1.1    List
1.1.1    ArrayList
     动态数组
    实现list接口,非同步
    有序的排列
    最好设置length长度,不然会引起内存泄露
     查询很快,删除新增较慢(因为需要移动数据)
1.1.2    linkedList
    双向列表结构
    Fail-fast
(fail-fast 迭代器,这意味着它们假设线程在集合内容中进行迭代时,集合不会更改它的内容。如果 fail-fast 迭代器检测到在迭代过程中进行了更改操作,那么它会抛出 ConcurrentModificationException)
    从两边插入,查询较慢,新增删除较快(因为是指针移动)
    不容易内存泄露
1.2    Map
1.2.1    HashMap
非线程安全,单链表结构,容易造成死锁
键值对
非同步的
无序的,
get、set较快
1.2.2    linkedHashMap
有序的双链表结构,可以根据访问次数进行排序
1.2.3    ConcurremtHashMap
访问会走两步,一步是hash查找到segments,然后到HashEntry

ConcurremtHashMap在segments上加锁,HashTable不同的是,所有的key竞争一个锁
可以适用于高并发,多线程
线程安全
1),ConcurremtHashMap的锁分段技术
通过使用段(Segment)将ConcurrentHashMap划分为不同的部分,ConcurrentHashMap就可以使用不同的锁来控制对哈希表的不同部分的修改,从而允许多个修改操作并发进行, 这正是ConcurrentHashMap锁分段技术的核心内涵。
2),ConcurrentHashMap的读是否要加锁,为什么
不需要加锁
第一:使用volatile关键字会强制将修改的值立即写入主存;
第二:使用volatile关键字的话,当线程2进行修改时,会导致线程1的工作内存中缓存变量的缓存行无效(反映到硬件层的话,就是CPU的L1或者L2缓存中对应的缓存行无效);
第三:由于线程1的工作内存中缓存变量的缓存行无效,所以线程1再次读取变量的值时会去主存读取。总结
ConcurrentHashMap的get操作全程不需要加锁,这也是它比其他并发集合比如hashtable、用Collections.synchronizedMap()包装的hashmap;安全效率高的原因之一。
get操作全程不需要加锁是因为Node的成员val是用volatile修饰的和数组用volatile修饰没有关系。
数组用volatile修饰主要是保证在数组扩容的时候保证可见性。
3),ConcurrentHashMap的迭代器是强一致性的迭代器还是弱一致性的迭代器
弱一致迭代器

1.2.4    volatile 关键字
一个被共享的变量被volatile修饰之后便具备了两层含义
1),不同的线程对这个变量进行操作时的可见性,即一个线程修改了这个可变变量,这个新值对其他线程来说是立即更新的
2),禁止处理器进行性重排序
3),但是不能保证原子性
1.2.5    三种特性
    1),原子性(适用于高并发所考虑的事情)
    2),可见性(适用于多个线程修改同一个变量时,可能会考虑的事情)
    3),有序性
        Int a = 0;    T1
        Int b = 1;    T2
        A=a+1;    T3
        B = a*a;    T41
(处理器会进行重新排序, T4一定在T3后面执行,因为T4对T3有依赖性)

自己整理的,之后复习用的。如果有不对欢迎留言,我会改进的。
 

猜你喜欢

转载自blog.csdn.net/Jon_jing/article/details/83145217