线程安全原理简析及HashMap多线程并发5种场景异常分析(1)

简介: 线程安全原理简析及HashMap多线程并发5种场景异常分析(1)

多线程并发出现异常的情况


单例模式


public class DoubleCheckSingleton {
    /**
     * 使用volatile,在多线程场景下,确保在判断null时,对所有线程可见
     */
    private static volatile DoubleCheckSingleton uniqInstance;
    /**
     * 构造器私有,防止外部实例化该类
     */
    private DoubleCheckSingleton() {}
    /**
     * 静态方法实例化,由于在类内部,可以调用构造器
     */
    public static DoubleCheckSingleton getInstance(){
        if (null == uniqInstance) { // 此处判断需要可见性volatile
            synchronized (DoubleCheckSingleton.class) {
                if (null == uniqInstance) {
                    //延迟初始化
                    uniqInstance = new DoubleCheckSingleton();
                }
            }
        }
        return uniqInstance;
    }
}


可见性


  • 引发原因


CPU高速缓存 由于各个线程会在执行是从 主存 加载到CPU高速缓存中执行,节省读取内存时间(CPU速度>> 主存速度)


image.png


线程A对共享变量V做了修改,其它线程B看到V的值还是之前的old失效数据


  • 后果(以单例模式举例)


失效数据


线程A已经创建了instance,但是线程B读取的instance还是null,会导致创建了两个instance,A和B拿到的实例不一样!!


失效值可能导致错误的结果或者导致活跃性问题。


  • fix方案


volatile


加锁(syn、lock)


有序性


  • 引发原因


编译优化之指令重排序


CPU执行指令时会有一些指令重排序以期最大效率


image.png


  • 后果(以单例模式举例)



单例模式赋值和实例化的重排序导致的异常


image.png


  • fix方案


volatile


加锁


通过Happens-before规则实现


内置锁的释放锁操作发生在该锁随后的加锁操作之前


一个volatile变量的写操作发生在这个volatile变量随后的读操作之前


原子性


  • 引发原因


线程切换


CPU调度是时间片轮转如下图


image.png


public方法如有对共享变量读取-修改-写入等类型有依赖的操作序列时,需要是原子性完成

自增、先检查后执行

相关文章
|
3天前
|
数据采集 存储 Java
高德地图爬虫实践:Java多线程并发处理策略
高德地图爬虫实践:Java多线程并发处理策略
|
5天前
|
Java
并发编程之线程池的底层原理的详细解析
并发编程之线程池的底层原理的详细解析
15 0
|
18天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
22天前
|
Java 调度
Java并发编程:深入理解线程池的原理与实践
【4月更文挑战第6天】本文将深入探讨Java并发编程中的重要概念——线程池。我们将从线程池的基本原理入手,逐步解析其工作过程,以及如何在实际开发中合理使用线程池以提高程序性能。同时,我们还将关注线程池的一些高级特性,如自定义线程工厂、拒绝策略等,以帮助读者更好地掌握线程池的使用技巧。
|
30天前
|
存储 缓存 NoSQL
Redis单线程已经很快了6.0引入多线程
Redis单线程已经很快了6.0引入多线程
31 3
|
1月前
|
消息中间件 安全 Linux
线程同步与IPC:单进程多线程环境下的选择与权衡
线程同步与IPC:单进程多线程环境下的选择与权衡
58 0
|
3天前
|
安全 算法 Java
JavaSE&多线程&线程池
JavaSE&多线程&线程池
17 7
|
3天前
|
SQL Dubbo Java
案例分析|线程池相关故障梳理&总结
本文作者梳理和分享了线程池类的故障,分别从故障视角和技术视角两个角度来分析总结,故障视角可以看到现象和教训,而技术视角可以透过现象看到本质更进一步可以看看如何避免。
|
4天前
|
存储 缓存 NoSQL
为什么Redis使用单线程 性能会优于多线程?
在计算机领域,性能一直都是一个关键的话题。无论是应用开发还是系统优化,我们都需要关注如何在有限的资源下,实现最大程度的性能提升。Redis,作为一款高性能的开源内存数据库,因其出色的单线程性能而备受瞩目。那么,为什么Redis使用单线程性能会优于多线程呢?
17 1
|
9天前
|
安全 Java
深入理解 Java 多线程和并发工具类
【4月更文挑战第19天】本文探讨了Java多线程和并发工具类在实现高性能应用程序中的关键作用。通过继承`Thread`或实现`Runnable`创建线程,利用`Executors`管理线程池,以及使用`Semaphore`、`CountDownLatch`和`CyclicBarrier`进行线程同步。保证线程安全、实现线程协作和性能调优(如设置线程池大小、避免不必要同步)是重要环节。理解并恰当运用这些工具能提升程序效率和可靠性。