Java多线程之volatile详解,夯实你的开发基础

Java基础:volatile详解 Java基础:volatile1、volatile保证可见性1.1、JMM模型的引入1.2、volatile保证可见性的代码验证1.2.1、无可见性代码验证1.2.1、volatile保证可见性验证2、volatile不保证原子性 问:请谈谈你对volatile的理解? 答:volatile是Java虚拟机提供的轻量级的同步机制,它有3个特性: 1)保证可见性 2)不保证原子性 3)禁止指令重排 刚学完java基础,如果有人问你什么是volatile?它有什么作用的话,相信一定非常懵逼… 可能看了答案,也完 阅读详情

从多线程交替打印A和B开始

面试中经常会有一道多线程交替打印A和B的问题,可以通过使用Lock和一个共享变量来完成这一操作,代码如下,其中使用num来决定当前线程是否打印

public class ABTread {
    private static int num=0;
    private static Lock lock=new ReentrantLock();
    public static void main(String[] args) throws InterruptedException {
        Thread A=new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    lock.lock();
                    if (num==0){
                        System.out.println("A");
                        num=1;
                    }                    lock.unlock();
                }            }        },"A");
        Thread B=new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    lock.lock();
                    if (num==1){
                        System.out.println("B");
                        num=0;
                    }                    lock.unlock();
                }            }        },"B");
        A.start();        B.start();    }}

这一过程使用了一个可重入锁,在以前可重入锁的获取流程中有分析到,当锁被一个线程持有时,后继的线程想要再获取锁就需要进入同步队列还有可能会被阻塞。

现在假设当A线程获取了锁,B线程再来获取锁且B线程获取失败则会调用LockSupport.park()导致线程B阻塞,线程A释放锁时再还行线程B。

是否会经常存在阻塞线程和还行线程的操作呢,阻塞和唤醒的操作是比较费时间的。是否存在一个线程刚释放锁之后这一个线程又再一次获取锁,由于共享变量的存在,则获取锁的线程一直在做着毫无意义的事情。

可以使用volatile关键字来修饰共享变量来解决,代码如下:

public class ABTread {
    private static volatile  int num=0;
    public static void main(String[] args) throws InterruptedException {
        Thread A=new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    if (num==0){        //读取num过程记作1
                        System.out.println("A");
                        num=1;          //写入num记位2
                    }
                }
            }
        },"A");
        Thread B=new Thread(new Runnable() {
            @Override
            public void run() {
                while (true){
                    if (num==1){        //读取num过程记作3
                        System.out.println("B");
                        num=0;          ////写入num记位4
                    }
                }
            }
        },"B");
        A.start();
        B.start();
    }
}

Lock可以通过阻止同时访问来完成对共享变量的同时访问和修改,必要的时候阻塞其他尝试获取锁的线程,那么volatile关键字又是如何工作,在这个例子中,是否效果会优于Lock呢。

Java 内存模型中的可见性、原子性和有序性

  • 可见性:值线程之间的可见性,一个线程对于状态的修改对另一个线程是可见的,也就是说一个线程修改的结果对于其他线程是实时可见的。
    可见性是一个复杂的属性,因为可见性中的错误总是会违背我们的直觉(JMM决定),通常情况下,我们无法保证执行读操作的线程能实时的看到其他线程的写入的值。为了保证线程的可见性必须使用同步机制。退一步说,最少应该保证当一个线程修改某个状态时,而这个修改时程序员希望能被其他线程实时可见的,那么应该保证这个状态实时可见,而不需要保证所有状态的可见。在 Java 中 volatile、synchronized 和 final 实现可见性。
  • 原子性:如果一个操作是不可以再被分割的,那么我们说这个操作是一个原子操作,即具有原子性。但是例如i++实际上是i=i+1这个操作是可分割的,他不是一个原子操作。
    非原子操作在多线程的情况下会存在线程安全性问题,需要是我们使用同步技术将其变为一个原子操作。java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。在 Java 中 synchronized 和在 lock、unlock 中操作保证原子性
  • 有序性:一系列操作是按照规定的顺序发生的。如果在本线程之内观察,所有的操作都是有序的,如果在其他线程观察,所有的操作都是无序的;前半句指“线程内表现为串行语义”后半句指“指令重排序”和“工作内存和主存同步延迟”
    Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性。volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。

Volatile原理

volatile定义:Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致的更新,线程应该通过获取排他锁单独获取这个变量;
java提供了volatile关键字在某些情况下比锁更好用。

  • Java语言提供了volatile了关键字来提供一种稍弱的同步机制,他能保证操作的可见性和有序性。当把变量声明为volatile类型后,
    编译器与运行时都会注意到这个变量是一个共享变量,并且这个变量的操作禁止与其他的变量的操作重排序。
  • 访问volatile变量时不会执行加锁操作。因此也不会存在阻塞竞争的线程,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。

volatile的特性

volatile具有以下特性:

  • 可见性:对于一个volatile的读总能看到最后一次对于这个volatile变量的写
  • 原子性:对任意单个volatile变量的读/写具有原子性,但对于类似于i++这种复合操作不具有原子性。
  • 有序性:

volatile happens-before规则

根据JMM要求,共享变量存储在共享内存当中,工作内存存储一个共享变量的副本,
线程对于共享变量的修改其实是对于工作内存中变量的修改,如下图所示:

Java多线程之volatile详解,夯实你的开发基础

 

以从多线程交替打印A和B开始章节中使用volatile关键字的实现为例来研究volatile关键字实现了什么:
假设线程A在执行num=1之后B线程读取num指,则存在以下happens-before关系

1)  1 happens-before 2,3 happens-before 4
2)  根据volatile规则有:2 happens-before 3
3)  根据heppens-before传递规则有: 1 happens-before 4

至此线程的执行顺序是符合我们的期望的,那么volatile是如何保证一个线程对于共享变量的修改对于其他线程可见的呢?

volatile 内存语义

根据JMM要求,对于一个变量的读写存在8个原子操作。对于一个共享变量的读写过程如下图所示:

Java多线程之volatile详解,夯实你的开发基础

 

对于一个没有进行同步的共享变量,对其的使用过程分为read、load、use、assign以及不确定的store、write过程。
整个过程的语言描述如下:

- 第一步:从共享内存中读取变量放入工作内存中(`read`、`load`)
- 第二步:当执行引擎需要使用这个共享变量时从本地内存中加载至**CPU**中(`use`)
- 第三步:值被更改后使用(`assign`)写回工作内存。
- 第四步:若之后执行引擎还需要这个值,那么就会直接从工作内存中读取这个值,不会再去共享内存读取,除非工作内存中的值出于某些原因丢失。- 第五步:在不确定的某个时间使用`store`、`write`将工作内存中的值回写至共享内存。

由于没有使用锁操作,两个线程可能同时读取或者向共享内存中写入同一个变量。或者在一个线程使用这个变量的过程中另一个线程读取或者写入变量。
即上图中1和6两个操作可能会同时执行,或者在线程1使用num过程中6过程执行,那么就会有很严重的线程安全问题,
一个线程可能会读取到一个并不是我们期望的值。

那么如果希望一个线程的修改对后续线程的读立刻可见,那么只需要将修改后存储在本地内存中的值回写到共享内存
并且在另一个线程读的时候从共享内存重新读取而不是从本地内存中直接读取即可;事实上
当写一个volatile变量时,JMM会把该线程对应的本地内存中共享变量值刷新会共享内存;
而当读取一个volatile变量时,JMM会从主存中读取共享变量
,这也就是volatile的写-读内存语义。

volatile的写-读内存语义:

volatile写的内存语义:当写一个volatile变量时,JMM会把该线程对应的本地内存中共享变量值刷新会共享内存volatile读的内存语义:当读一个volatile变量时,JMM会把该线程对应的本地内存置为无效,线程接下来将从主内存中读取共享变量。

如果将这两个步骤综合起来,那么线程3读取一个volatile变量后,写线程1在写这个volatile变量之前所有可见的共享变量的值都将乐客变得对线程3可见。

volatile变量的读写过程如下图:

Java多线程之volatile详解,夯实你的开发基础

 

需要注意的是:在各个线程的工作内存中是存在volatile变量的值不一致的情况的,只是每次使用都会从共享内存读取并刷新,执行引擎看不到不一致的情况,
所以认为volatile变量在本地内存中不存在不一致问题。

volatile 内存语义的实现

在前文Java内存模型中有提到重排序。为了实现volatile的内存语义,JMM会限制重排序的行为,具体限制如下表:

是否可以重排序第二个操作第二个操作第二个操作第一个操作普通读/写volatile读volatile写普通读/写NOvolatile读NONONOvolatile写NONO

说明:

- 若第一个操作时普通变量的读写,第二个操作时volatile变量的写操作,则编译器不能重排序这两个操作
- 若第一个操作是volatile变量的读操作,不论第二个变量是什么操作不饿能重排序这两个操作
- 若第一个操作时volatile变量的写操作,除非第二个操作是普通变量的独写,否则不能重排序这两个操作

为了实现volatile变量的内存语义,编译器生成字节码文件时会在指令序列中插入内存屏障来禁止特定类型的处理器排序。
为了实现volatile变量的内存语义,插入了以下内存屏障,并且在实际执行过程中,只要不改变volatile的内存语义,
编译器可以根据实际情况省略部分不必要的内存屏障

- 在每个volatile写操作前面插入StoreStore屏障
- 在每个volatile写操作后面插入StoreLoad屏障
- 在每个volatile读操作后面插入LoadLoad屏障
- 在每个volatile读操作后面插入LoadStore屏障

插入内存屏障后volatile写操作过程如下图:

Java多线程之volatile详解,夯实你的开发基础

插入内存屏障后volatile读操作过程如下图:

Java多线程之volatile详解,夯实你的开发基础

 

至此在共享内存和工作内存中的volatile的写-读的工作过程全部完成

但是现在的CPU中存在一个缓存,CPU读取或者修改数据的时候是从缓存中获取并修改数据,那么如何保证CPU缓存中的数据与共享内存中的一致,并且修改后写回共享内存呢?

CPU对于Volatile的支持

缓存行:cpu缓存存储数据的基本单位,cpu不能使数据失效,但是可以使缓存行失效。

对于CPU来说,CPU直接操作的内存时高速缓存,而每一个CPU都有自己L1、L2以及共享的L3级缓存,如下图:

Java多线程之volatile详解,夯实你的开发基础

 

那么当CPU修改自身缓存中的被volatile修饰的共享变量时,如何保证对其他CPU的可见性。

缓存一致性协议

在多处理器的情况下,每个处理器总是嗅探总线上传播的数据来检查自己的缓存是否过期,当处理器发现自己对应的缓存对应的地址被修改,
就会将当前处理器的缓存行设置为无效状态,当处理器对这个数据进行操作的时候,会重新从系统中把数据督导处理器的缓存里。这个协议被称之为缓存一致性协议。

缓存一致性协议的实现又MEI、MESI、MOSI等等。

MESI协议缓存状态

状态描述M(modified)修改该缓存指被缓存在该CPU的缓存中并且是被修改过的,即与主存中的数据不一致,该缓存行中的数据需要在未来的某个时间点写回主存,当写回注册年之后,该缓存行的状态会变成E(独享)E(exclusive)独享该缓存行只被缓存在该CPU的缓存中,他是未被修改过的,与主存中数据一致,该状态可以在任何时候,当其他的CPU读取该内存时编程共享状态,同样的,当CPU修改该缓存行中的内容时,该状态可以变为M(修改)S(share)共享该状态意味着该缓存行可能被多个CPU缓存,并且各个缓存中的数据与主存中的数据一致,当有一个CPU修改自身对应的缓存的数据,其它CPU中该数据对应的缓存行被作废I(Invalid)无效该缓存行无效

MESI协议可以防止缓存不一致的情况,但是当一个CPU修改了缓存中的数据,但是没有写入主存,也会存在问题,那么如何保证CPU修改共享被volatile修饰的共享变量后立刻写回主存呢。

在有volatile修饰的共享变量进行写操作的时候会多出一条带有lock前缀的汇编代码,而这个lock操作会做两件事:

  1. 将当前处理器的缓存行的数据协会到系统内存。lock信号确保声言该信号期间CPU可以独占共享内存。在之前通过锁总线的方式,现在采用锁缓存的方式。
  2. 这个写回操作会使其他处理器的缓存中缓存了该地址的缓存行无效。在下一次这些CPU需要使用这些地址的值时,强制要求去共享内存中读取。

如果对声明了volatile的共享变量进行写,JVM会向CPU发送一条lock指令,使得将这个变量所在的缓存行缓存的数据写回到内存中。而其他CPU通过嗅探总线上传播的数据,
使得自身缓存行失效,下一次使用时会从主存中获取对应的变量。

工作内存(本地内存)并不存在

根据JAVA内存模型描述,各个线程使用自身的工作内存来保存共享变量,那么是不是每个CPU缓存的数据就是从工作内存中获取的。这样的话,在CPU缓存写回主存时,
协会的是自己的工作内存地址,而各个线程的工作内存地址并不一样。CPU嗅探总线时就嗅探不到自身的缓存中缓存有对应的共享变量,从而导致错误?

事实上,工作内存并不真实存在,只是JMM为了便于理解抽象出来的概念,它涵盖了缓存,写缓冲区、寄存器及其他的硬件编译器优化。所以缓存是直接和共享内存交互的。
每个CPU缓存的共享数据的地址是一致的。

总结

  • volatile提供了一种轻量级同步机制来完成同步,它可以保操作的可见性、有序性以及对于单个volatile变量的读/写具有原子性,对于符合操作等非原子操作不具有原子性。
  • volatile通过添加内存屏障及缓存一致性协议来完成对可见性的保证。

最后Lock#lock()是如何保证可见性的呢??

Lock#lock()使用了AQS的state来标识锁状态,而state是volatile标记的,由于对于volatile的独写操作时添加了内存屏障的,所以在修改锁状态之前,一定会将之前的修改写回共享内存。

Java volatile详解 一 简介 volatile是Java提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制:同步块(或方法)和 volatile 变量,相比于synchronized(synchronized通常称为重量级锁),volatile更轻量级,因为它不会引起线程上下文的切换和调度。但是volatile 变量的同步性较差(有时它更简单并且开销更低),而且其使用也更容易出错。 二 并发编程的3个基本概念 1.原子性 定义: 即一个操作或者多个操作要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 阅读详情

相关推荐

Java 多线程环境下 volatile 的性能调优

多线程编程的核心挑战是“数据一致性”:多个线程同时操作共享变量时,如何避免“你改了我看不见”(可见性问题)或“操作顺序乱套”(指令重排问题)。volatile是 Java 提供的轻量级解决方案,但它的性能表现(如内存屏障开销、总线风暴风险)常被忽视。本文将聚焦volatile在多线程环境下的性能调优,覆盖原理分析、常见误区、实战优化技巧。本文将按照“问题引入→核心概念→底层原理→性能瓶颈→调优策略→实战案例”的逻辑展开。

Java大师兄的博客 1033

Java中的volatile

​ volatile是Java提供的一种轻量级的同步机制,在并发编程中,它也扮演着比较重要的角色。同synchronized相比(synchronized通常称为重量级锁),volatile更轻量级,相比使用synchronized所带来的庞大开销,倘若能恰当的合理的使用volatile,自然是美事一桩。为了能比较清晰彻底的理解volatile,我们一步一步来分析。首先来看看如下代码 上面这个例子,模拟在多线程环境里,t1线程对flag共享变量修改的值能否被t2可见,即是否输出 “-----flag被设置为

HGW的博客 2万+

Java volatile关键字最全总结:原理剖析与实例讲解(简单易懂)

本文从Java的内存模型和线程的工作原理出发,对volatile关键字进行介绍。帮助读者深入理解volatile的工作机制。同时,还通过简单易懂的示例讲解了如何正确地使用volatile关键字实现线程安全,避免常见的多线程安全问题。

夏日清风 25万+

Java 之 volatile 详解

volatile 可以看做是轻量级的 synchronized,它只保证了共享变量的可见性,是Java虚拟机提供的轻量级的同步机制。在线程 A 修改被 volatile 修饰的共享变量之后,线程 B 能够读取到正确的值。Java 在多线程中操作共享变量的过程中,会存在指令重排序与共享变量工作内存缓存的问题。volatile 一共有三大特性,保证可见性不保证原子性禁止指令重排。

流华追梦的专栏 8520

RK3588嵌入式开发实战:U-Boot设备树文件修改全指南(含常见踩坑点)

本文为RK3588嵌入式开发者提供了一份详尽的U-Boot设备树文件修改实战指南。文章深入解析了设备树的核心架构,从基础硬件适配到时钟、电源管理等进阶配置,并重点总结了内存节点、串口输出、电源时序等常见踩坑点与解决方案,旨在帮助开发者高效、稳健地完成U-Boot移植与定制工作。

yhn456789的博客 732

Win11+VSCode+TeXLive:学术党必备的LaTeX环境配置避坑指南(2024最新版)

本文详细介绍了如何在Windows 11系统下,通过VSCode编辑器与TeXLive发行版配置高效的LaTeX学术写作环境。针对国内用户常见的镜像下载慢、插件配置复杂等问题,提供了优化方案和避坑指南,帮助科研人员和学生快速搭建流畅的学术写作工作流。

plum99的博客 619

java中多线程之volatile详解(最通俗)

java中多线程之volatile详解     什么是volatile volatile是JVM提供的轻量级同步机制 好,开始讲大家看不懂的东西了! volatile有三大特性: 保证可见性 不保证原子性 禁止指令重排 傻了吧,这他妈都是些什么jb东西啊?别着急,我们一个一个来。 在学习volatile之前,我们先了解一下JMM。什么又是JMM?我只知道JVM。这他妈是啥东西啊? JMM:java内存模型。jmm是一种抽象的概念,并不真实存在,它描述的是一种规范,通过这种规范定义了程序中的各个变量的访问

易柏州的博客 1万+

用Typora画流程图和序列图:Mermaid语法实战教程(含常见报错解决)

本文是一份详细的Typora与Mermaid语法实战教程,教你如何在Markdown文档中高效绘制流程图和序列图。文章涵盖从环境配置、核心语法到复杂图表构建的全过程,并重点解析了常见报错原因与解决方案,助你将可视化图表无缝融入文档工作流。

weixin_29279101的博客 299

【Java基础】volatile关键字

关于作者:优快云内容合伙人、技术专家, 从零开始做过日活千万级APP。专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

fumeidonga的博客 5088

WiFi偏门协议(四):增强的传输机制802.11aa

区分Unicast和Multicast的优先级,以及设定不同的重传次数,以细化EDCA机制。 SCS(StreamClassification Service) 如上图,在VI,VO内各自又增加了一个queue, 对应不同的MAC header。VI和VO内的两个queue可以分别对应UC和MC。这样就提供了同一个AC内的更细粒度的优先级区分。当然还可以使用Drop Eligibility Indication子域来区分不同的重传次数。 改善Multicast数据传...

reekyli的专栏 1790

Vue3 - Element Plus上传组件el-upload上传多个文件时,让on-change监听事件仅执行一次并获取最终文件列表方法(开启多选文件并手动上传,拿到文件列表统一循环调用接口上传)

vue3,elementplus,Upload上传,el-upload,文件上传组件,上传组件on-change里执行多次,取消自动上传后change重复执行问题,upload上传多个文件后导致on-change执行多次拿不到最终文件列表,Element-plus的upload组件on-change不断执行怎么办,上传多个文件多次执行调用,上传多个文件时如何只执行一次on-change方法拿到最终的文件列表,vue3elementplus上传组件开启多个上传后导致change方法执行好几次,仅调用一

🏆 前端领域优质创作者 1万+

JAVA多线程以及volatile关键字详解

上述代码T1线程中当qiut等于0的时候一个线程在不停的循环,另外一个线程T2中写入了scanner来改变quit的值 按照理论来讲,如果我们此时输入0以外的数字,比如输入1,T1线程中拿到quit等于1然后就会跳出循环执行下面的打印方法.(此时只有一个线程在操作变量不需要使用synchronized)但是运行程序可知。原因是原来在我们编写程序的时候开发JVM虚拟机,和java等编译器的工作人员会对我们的代码,在不改变原有逻辑的基础上进行一部分的优化.以便提高代码的执行效率。所以最后结果为10w了。

a512512a的博客 2152

Vue3 - 详细实现流程图编辑器可视化平台示例代码,打造前端web网页流程图在线编辑绘制操作展示,vue3自定义绘制流程图在页面上画流程图功能(提供各种操作按钮及节点控件,界面美观交互式流程图插件)

vue3,绘制流程图,在线流程图制作,在vue3中实现流程图,vue3做一个制作流程图的功能,vue3流程图组件,vue3流程图,流程图绘制展示,vue3流程图可视化在线编辑源码,基于VUE3的在线绘制流程图工具,vue3+logicflow流程图,绘制动态流程图并自定义节点和线,vue使用logicFlow绘制流程图,生成各种流程图图形可连接点移除,基于Vue的流程图组件,工作流程图,流程编辑器,vue3流程组件,vue-flow绘制流程图,绘制流程图示例demo,vue3 logicflow流程图使用教

🏆 前端领域优质创作者 9967

volatile关键字详解

缓存一致性协议: 每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了,当处理器发现自己缓存行对应的内存地址被修改,就会将当前处理器的缓存行设置成无效状态,当处理器要对这个数据进行修改操作的时候,会强制重新从系统内存里把数据读到处理器缓存里。在多线程环境下,CPU轮流切换线程执行,有可能某个线程修改了数据,准备回主内存,此时CPU切换到另一个线程修改了数据,并且写回到了主内存,此时就导致数据的不准确。的作用就是,当某个线程工作内存中的值与主内存中的值,如果不相同就会一直。

努力分享一些干货 1837

华为OD机试 - 取出尽量少的球 - 感谢@吴修柯反馈(Python/JS/C/C++ 双机位A卷 200分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。感谢@吴修柯反馈,2025-03-22,A卷200分考试真题。某部门开展 Family Day 开放日活动,其中有个从桶里取球的游戏。有 N 个容量一样的小桶等距排开,且每个小桶都默认装了数量不等的小球,每个小桶装的小球数量记录在数组 bucke

学Java,找哪吒 1485

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Java多线程volatile详解

volatile定义Java编程语言允许线程访问共享变量,为了确保共享变量能被准确和一致地更新,线程应该确保通过排他锁单独获得这个变量。Java语言提供了volatile,在某些情况下比锁要更加方便。如果一个字段被声明成volatile,Java线程内存模型确保所有线程看到这个变量的值是一致的。volatile的作用先让我们说说volatile关键字的作用。它在多处理器开发中保证了共享变量的“可见性

路漫漫,水迢迢 6276

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

java多线程(并发)夯实之路-volatile深入浅出

volatile(易变关键字)可以用来修饰成员变量和静态成员变量,线程只能从主存中获取它的值,线程操作volatile变量都是直接操作主存。 与synchronzied区别:synchronzied需要创建Monitor,属于重量级的操作,volatile更轻量(推荐)

qq_61282807的博客 1238

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

java基础—Volatile关键字详解

volatile详解—并发编程3大特性、volatile从CPU层面和JMM层面如何保证可见性、有序性,为什么不能保证原子性、happens-before讲解以及案例演示

江哈哈的博客 4715

java volatile 关键字详解

java volatile 关键字详解 一,什么是volatile关键字,作用是什么 ​ volatile是java虚拟机提供的轻量级同步机制 ​ 作用是: 1.保证可见性 2.禁止指令重排 3.不保证原子性 本篇具体就讲解 什么叫保证了可见性, 什么叫禁止指令重排,什么是原子性 而在这之前需要对JMM 有所了解 二,什么是JMM ​ JMM(java 内存模型 Java Memory Model 简称JMM) 本身是一个抽象的概念,并不在内存中真实存在的,它描述的

clinginh的博客 9724

【java必备】Java 多线程安全之 volatile 关键字详解

volatile是一个 Java 语言的关键字,用来修饰成员变量和静态成员变量。当一个变量被声明为volatile类型时,它会告知 JVM 该变量可能会被多个线程同时访问,因此每次读写这个变量的时候都必须直接从主内存中进行,而不是缓存到寄存器或本地内存。

王大师企业官方博客 3257

volatile详解

保证可见性禁止指令重排序性能开销小使用简单。

weixin_74417835的博客 9906

JAVA多线程基础篇-关键字volatile

1.概述 volatile是java多线程中一个常见的关键字,面试中被问的频率也比较高。那么volatile的作用是什么?以及其实现原理是什么?本文将基于上述问题,结合一些具体案例来分析volatile的作用以及实现原理,来帮助大家更好地理解volatile。 2.案例分析 ...

qq_33479841的博客 2210
上一篇: 牛皮!阿里P8联合多位业界大佬整理的架构宝典,升职加薪有奇效
下一篇: 漫谈架构演变之路:为何要搞微服务架构?今天就为大家讲透!
Java领域指导者
博客等级 码龄7年 404粉丝 265原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值