Atomic&Collections
1、Atomic
原子操作,即不能被分割的最小粒子
1.1 Atomiclnteger的使用场景
AtomicInteger提供原子操作来进行Integer的使用,适合并发情况下的使用,比如两个线程对同一个整数累加。
1.2 为什么Atomiclnteger是线程安全的,原理是什么
AtomicInteger是对int类型的一个封装,提供原子性的访问和更新操作,其原子性操作的实现是基于CAS(compare-and-swap)技术。CAS表现为一组指令,当利用CAS执行试图进行一些更新操作时,会首先比较当前数值,如果数值未变,代表没有其它线程进行并发修改,则成功更新。如果数值改变,则可能出现不同的选择,要么进行重试,要么就返回是否成功。也就是所谓的“乐观锁”。
1.3 Atomiclnteger的CAS机制会导致什么问题
会导致ABA问题,操作对象,获取对象后,执行CAS操作前,被其他线程修改后,且又修改为原来的对象值,导致CAS忽略其他线程的修改,成功执行CAS对象修改。 从Java1.5开始JDK的atomic包里提供了一个类AtomicStampedReference来解决ABA问题。这个类的compareAndSet方法作用是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
1.4 用volatile修饰变量不可以吗
volatile只是保证能够从主内存中取到最新的值,但是不能保证并发的正确性
2、HashMap
数据结构:数组+链表+(红黑树jdk>=1.8)
重要成员变量:
3、ConcurrentHashMap
数据结构:数据结构与HashMap类似
区别:① 内部在数据写入时加了同步机制保证线程安全,读操作是无锁操作
② 扩容时老数据的转移是并发执行的,这样效率更高
4、CopyOnWrite机制
读写分离,空间换时间,避免为保证并发安全导致的激烈的锁的竞争。
关键点:
① CopyOnWrite适用于读多写少的情况,最大程度的提高读的效率;
② CopyOnWrite是最终一致性,在写的过程中,原有读的数据是不会发生更新的,只有新的读才能读到新数据
③ 如果需要其他线程及时的读到数据,需要使用volatile变量
④ 写的时候不能并发写,需要对写操作进行加锁
优点:
对于一些读多写少的数据,写入时复制的做法就很不错,例如配置、黑名单、物流地址等变化非常少的数据,这是一种无锁的实现。可以帮我们实现程序更高的并发。
CopyOnWriteArrayList 并发安全且性能比 Vector 好。Vector 是增删改查方法都加了synchronized 来保证同步,但是每个方法执行的时候都要去获得锁,性能就会大大下降,而 CopyOnWriteArrayList 只是在增删改上加锁,但是读不加锁,在读方面的性能就好于 Vector。
缺点:
数据一致性问题。这种实现只是保证数据的最终一致性,在添加到拷贝数据而还没进行替换的时候,读到的仍然是旧数据。
内存占用问题。如果对象比较大,频繁地进行替换会消耗内存,从而引发 Java 的 GC 问题,这个时候,我们应该考虑其他的容器,例如 ConcurrentHashMap。