【多线程:volatile】原理

简介: 【多线程:volatile】原理

【多线程:volatile】原理

01.介绍

volatile的底层实现原理是内存屏障

1.对volatile变量的写指令后会加入写屏障
2.对volatile变量的读指令前会加入读屏障

02.volatile保证可见性原理

写屏障:保证在该屏障之前的,对共享变量的改动都同步到主存当中。

    public void actor2(I_Result r){
        num = 2;
        ready = true; // ready是volatile修饰的,且ready是写操作
        // ready后有写屏障
    }

读屏障:保证在该屏障之后,对共享变量的读取,加载的是主存中的最新数据

    public void actor1(I_Result r){
        // 因为ready是读操作
        // 在ready之前有读屏障
        if(ready){
            r.r1 = num + num;
        }else{
            r.r1 = 1;
        }
    }

解释

写屏障可以保证自己和自己之前的共享变量 都同步到主存中,就像这里的num = 2是在ready = true之前,那么共享变量ready与num都会同步到主存当中
读屏障则是可以保证自己和自己之后的共享变量读取都是最新的,例如这里if(ready)就读取了ready 还有 r.r1 = num + num,这里读取了num
总结:通过读写屏障保证了 加了volatile的变量不论是写还是对都是最新的数据,且 对于写之前 读之后的数据也都是最新数据。这就是可见性实现的原理。

03.volatile保证有序性原理

写屏障:确保指令重排序时,不会将写屏障之前的代码排在写屏障之后。

    public void actor2(I_Result r){
        num = 2;
        ready = true; // ready是volatile修饰的,且ready是写操作
        // ready后有写屏障
    }

读屏障:确保指令重排序时,不会将读屏障之后的代码排在读屏障之前。

    public void actor1(I_Result r){
        // 因为ready是读操作
        // 在ready之前有读屏障
        if(ready){
            r.r1 = num + num;
        }else{
            r.r1 = 1;
        }
    }

解释

写屏障确保指令重排序时,不会将写屏障之前的代码排在写屏障之后,例如这个例子中的ready = true是读操作,保证了ready之前的代码不会出现在ready之后
读屏障则是确保指令重排序时,不会将读屏障之后的代码排在写屏障之前,例如这个例子中的if(ready)保证了ready之后的代码不会出现在ready之前,不过这里ready不存在这个问题 因为这里只有ready为true时才能进入
总结:通过读写屏障保证了 加了volatile的变量写之前的代码不会出现在写屏障之后 这就保证了 这个变量的位置固定,同时读屏障保证了读屏障之后的代码不会出现在读屏障之前 也保证了位置固定,所以在写这个变量时 这个变量不会出现指令重排序,读这个变量时 这个变量也不会出现指令重排序,保证了有序性。

目录
相关文章
|
1月前
|
安全 Java 数据库
一天十道Java面试题----第四天(线程池复用的原理------>spring事务的实现方式原理以及隔离级别)
这篇文章是关于Java面试题的笔记,涵盖了线程池复用原理、Spring框架基础、AOP和IOC概念、Bean生命周期和作用域、单例Bean的线程安全性、Spring中使用的设计模式、以及Spring事务的实现方式和隔离级别等知识点。
|
1月前
|
编解码 网络协议 API
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
|
1月前
|
存储 SQL 缓存
揭秘Java并发核心:深度剖析Java内存模型(JMM)与Volatile关键字的魔法底层,让你的多线程应用无懈可击
【8月更文挑战第4天】Java内存模型(JMM)是Java并发的核心,定义了多线程环境中变量的访问规则,确保原子性、可见性和有序性。JMM区分了主内存与工作内存,以提高性能但可能引入可见性问题。Volatile关键字确保变量的可见性和有序性,其作用于读写操作中插入内存屏障,避免缓存一致性问题。例如,在DCL单例模式中使用Volatile确保实例化过程的可见性。Volatile依赖内存屏障和缓存一致性协议,但不保证原子性,需与其他同步机制配合使用以构建安全的并发程序。
57 0
|
6天前
|
存储 缓存 Java
什么是线程池?从底层源码入手,深度解析线程池的工作原理
本文从底层源码入手,深度解析ThreadPoolExecutor底层源码,包括其核心字段、内部类和重要方法,另外对Executors工具类下的四种自带线程池源码进行解释。 阅读本文后,可以对线程池的工作原理、七大参数、生命周期、拒绝策略等内容拥有更深入的认识。
什么是线程池?从底层源码入手,深度解析线程池的工作原理
|
2月前
|
缓存 安全 算法
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
25 0
|
27天前
|
存储 NoSQL Java
线程池的原理与C语言实现
【8月更文挑战第22天】线程池是一种多线程处理框架,通过复用预创建的线程来高效地处理大量短暂或临时任务,提升程序性能。它主要包括三部分:线程管理器、工作队列和线程。线程管理器负责创建与管理线程;工作队列存储待处理任务;线程则执行任务。当提交新任务时,线程管理器将其加入队列,并由空闲线程处理。使用线程池能减少线程创建与销毁的开销,提高响应速度,并能有效控制并发线程数量,避免资源竞争。这里还提供了一个简单的 C 语言实现示例。
|
1月前
|
存储 Java
线程池的底层工作原理是什么?
【8月更文挑战第8天】线程池的底层工作原理是什么?
74 8
|
17天前
|
安全 Java API
Java线程池原理与锁机制分析
综上所述,Java线程池和锁机制是并发编程中极其重要的两个部分。线程池主要用于管理线程的生命周期和执行并发任务,而锁机制则用于保障线程安全和防止数据的并发错误。它们深入地结合在一起,成为Java高效并发编程实践中的关键要素。
10 0
|
2月前
|
存储 SQL Java
(七)全面剖析Java并发编程之线程变量副本ThreadLocal原理分析
在之前的文章:彻底理解Java并发编程之Synchronized关键字实现原理剖析中我们曾初次谈到线程安全问题引发的"三要素":多线程、共享资源/临界资源、非原子性操作,简而言之:在同一时刻,多条线程同时对临界资源进行非原子性操作则有可能产生线程安全问题。
|
30天前
|
缓存 Java
【多线程面试题二十三】、 说说你对读写锁的了解volatile关键字有什么用?
这篇文章讨论了Java中的`volatile`关键字,解释了它如何保证变量的可见性和禁止指令重排,以及它不能保证复合操作的原子性。