Java集合如何保证线程安全?Fail-fast、Fail-safe机制是什么?

有个学弟在面快手的时候,被问到Java非线程安全的集合,如HashMap,ArrayList是如何保证线程安全的时候犯了难,也没想到会问这么细,这篇文章将很快的说清楚这里的逻辑,发车~

一些源码

首先我们看看HashMap的一些关键代码: 我们注意到会有一个ModCount (修改计数)的属性,简而言之,容器在修改的时候会检查这个modCount是否与自己当前应该的modCount是否相同,不同的话就会快速失败,抛出ConcurrentModificationException,详情看下面的代码:

java 复制代码
public final void remove() {  
    Node<K,V> p = current;  
    if (p == null)  
        throw new IllegalStateException();  
    if (modCount != expectedModCount)  
        throw new ConcurrentModificationException();  
    current = null;  
    K key = p.key;  
    removeNode(hash(key), key, null, false, false);  
    expectedModCount = modCount;  
}

看这个方法就很清楚了,其他非线程安全集合如ArrayList也是这么处理的,ArrayList中直接封装了一个判断的方法:

java 复制代码
final void checkForComodification() {  
    if (modCount != expectedModCount)  
        throw new ConcurrentModificationException();  
}

Fail-fast

望文生义,fail-fast快速失败机制,是多线程并发操作集合时的一种失败处理机制。

在集合遍历过程中,一旦发现容器中的数据被修改了,会立刻抛出ConcurrentModificationException异常,从而导致遍历失败。

这里如果我一边遍历集合,一边添加元素,是会报ConcurrentModificationException的。

Fail-safe

Fail-safe:表示失败安全,也就是在这种机制下,出现集合元素的修改,不会抛出ConcurrentModificationException

原因是采用安全失败机制的集合容器,在遍历时不是直接在集合内容上访问的,而是先复制原有集合内容,

在拷贝的集合上进行遍历。由于迭代时是对原集合的拷贝进行遍历,所以在遍历过程中对原集合所作的修改并不能被迭代器检测到

比如这种情况

java 复制代码
public class Test {  
    public static void main(String[] args) {  
        CopyOnWriteArrayList<Integer> list = new CopyOnWriteArrayList<>(new Integer[]{1,7,9,11});  
        Iterator itr = list.iterator();  
        while(itr.hasNext()) {  
            Integer i = (Integer) itr.next();  
            System.out.println(i);  //是不会打印15的
            if(i==7){  
                list.add(15);  
            }  
        }  
    }  
}

定义了一个CopyOnWriteArrayList,在对这个集合遍历过程中,对集合元素做修改后,不会抛出异常,但同时也不会打印出增加的元素。

java.util.concurrent包下的容器都是安全失败的,可以在多线程下并发使用,并发修改。

常见的的使用Fail-safe方式遍历的容器有ConcerrentHashMap和CopyOnWriteArrayList等。

相关推荐
雨奔14 小时前
Kubernetes DNS 完全指南:服务发现核心机制与实践
java·kubernetes·服务发现
檀越剑指大厂14 小时前
32 万星的面试学习计划 + 内网穿透工具,程序员面试准备效率翻倍!
学习·面试·职场和发展
offer收割机小鹅14 小时前
大学生求职必备:AI面试、AI写作与设计工具助力职场发展
人工智能·ai·面试·aigc·ai写作
精神阿祝14 小时前
“八股文”在程序员面试中的价值:助力还是阻力?
面试·职场和发展
借雨醉东风14 小时前
程序分享--常见算法/编程面试题:旋转矩阵
c++·线性代数·算法·面试·职场和发展·矩阵
逻辑驱动的ken14 小时前
Java高频面试考点场景题14
java·开发语言·深度学习·面试·职场和发展·求职招聘·春招
阿冰冰呀15 小时前
互联网大厂Java求职面试实录:谢飞机的“水货”之路
java·mybatis·dubbo·springboot·线程池·多线程·hashmap
水无痕simon15 小时前
1.单机部署Nacos1.3.2
java
Java小生不才17 小时前
spring AI文生图
java·人工智能·spring ai
阿丰资源17 小时前
基于SpringBoot的在线视频教育平台的设计与实现(附源码+数据库+文档,一键运行)
数据库·spring boot·后端