皮皮网

【外卖卷源码】【koei 源码】【zxtouch源码】jvmvolatile源码

2024-11-19 09:33:18 来源:斯凯mrp源码

1.volatile关键字及其作用
2.synchronized和volatile区别
3.深入理解和使用volatile关键字

jvmvolatile源码

volatile关键字及其作用

       本文主要介绍Java语言中的volatile关键字,内容涵盖volatile的保证内存可见性、禁止指令重排等。

       1 保证内存可见性

       1.1 基本概念

       可见性是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是外卖卷源码一个线程修改的结果,另一个线程马上就能看到。

       1.2 实现原理

       当对非volatile变量进行读写的时候,每个线程先从主内存拷贝变量到CPU缓存中,如果计算机有多个CPU,每个线程可能在不同的CPU上被处理,这意味着每个线程可以拷贝到不同的CPU cache中。

       volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,保证了每次读写变量都从主内存中读,跳过CPU cache这一步。当一个线程修改了这个变量的koei 源码值,新值对于其他线程是立即得知的。

       2 禁止指令重排

       2.1 基本概念

       指令重排序是JVM为了优化指令、提高程序运行效率,在不影响单线程程序执行结果的前提下,尽可能地提高并行度。指令重排序包括编译器重排序和运行时重排序。

       在JDK1.5之后,可以使用volatile变量禁止指令重排序。针对volatile修饰的变量,在读写操作指令前后会插入内存屏障,指令重排序时不能把后面的指令重排序到内存屏障后面。

       2.2 指令重排带来的问题

       如果一个操作不是原子的,就会给JVM留下重排的机会。

       如果线程A中的指令发生了重排序,那么B中很可能就会拿到一个尚未初始化或尚未初始化完成的zxtouch源码context,从而引发程序错误。

       2.3 禁止指令重排的原理

       volatile关键字提供内存屏障的方式来防止指令被重排,编译器在生成字节码文件时,会在指令序列中插入内存屏障来禁止特定类型的处理器重排序。

       JVM内存屏障插入策略:

       每个volatile写操作的前面插入一个StoreStore屏障;

       在每个volatile写操作的后面插入一个StoreLoad屏障;

       在每个volatile读操作的后面插入一个LoadLoad屏障;

       在每个volatile读操作的后面插入一个LoadStore屏障。

       2.4 指令重排在双重锁定单例模式中的影响

       基于双重检验的单例模式(懒汉型)

       instance= new Singleton()并不是一个原子操作,其实际上可以抽象为下面几条JVM指令:

       上面操作2依赖于操作1,但是操作3并不依赖于操作2。所以JVM是可以针对它们进行指令的优化重排序的,经过重排序后如下:

       指令重排之后,instance指向分配好的内存放在了前面,而这段内存的初始化被排在了后面。在线程A执行这段赋值语句,在初始化分配对象之前就已经将其赋值给instance引用,恰好另一个线程进入方法判断instance引用不为null,然后就将其返回使用,ipts源码导致出错。

       解决办法

       用volatile关键字修饰instance变量,使得instance在读、写操作前后都会插入内存屏障,避免重排序。

       3 适用场景

       (1) volatile是轻量级同步机制。在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,是一种比synchronized关键字更轻量级的同步机制。

       (2) volatile**无法同时保证内存可见性和原子性。加锁机制既可以确保可见性又可以确保原子性,而volatile变量只能确保可见性**。

       (3) volatile不能修饰写入操作依赖当前值的变量。声明为volatile的简单变量如果当前值与该变量以前的值相关,那么volatile关键字不起作用,baidu源码也就是说如下的表达式都不是原子操作:“count++”、“count = count+1”。

       (4) 当要访问的变量已在synchronized代码块中,或者为常量时,没必要使用volatile;

       (5) volatile屏蔽掉了JVM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。

       想获取更多知识和学习资料可以扫描下方二维码或是点击链接

       mp.weixin.qq.com/s/vkvY...

synchronized和volatile区别

       synchronized和volatile区别:

       volatile本质:是java虚拟机(JVM)当前变量在工作内存中的值是不确定的,需要从主内存中读取;synchronized则是锁定当前的变量,只有当前线程可以访问到该变量,其他的线程将会被阻塞。

       扩展资料

       volatile只能实现变量的修改可见性,并不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。

       volatile只能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。

       volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

深入理解和使用volatile关键字

       大家好!今天小黑要和大家聊聊Java并发编程的一个重要话题——volatile关键字。在Java的世界里,掌握并发编程是一项必备技能,尤其是当咱们处理多线程应用时。你可能听说过这样的情况:即使你的代码看起来毫无问题,但在并发环境下,它们就像是刚从床上起来的头发,乱七八糟!为什么会这样呢?原因在于多线程操作时存在的一些难以察觉的陷阱,比如变量的可见性问题、操作的原子性问题等等。

       Java提供了多种机制来处理这些问题,其中volatile关键字就是一个重要的工具。可能有人会问,这个volatile到底是个什么东西?简单来说,它是Java提供的一种轻量级的同步机制。但别小看了这个“轻量级”,它在确保变量在多线程环境下的可见性方面,可是有着不可小觑的作用。在接下来的内容中,小黑将带你深入了解volatile,以及它在Java并发编程中的应用和局限性。

       好了,现在咱们来深入了解一下volatile这个“神秘”的关键字。在Java中,volatile是一种用于声明变量的修饰符。它告诉JVM和编译器,这个变量可能会被多个线程同时访问,而且还不通过锁来控制。这听起来有点像是给变量加了一个“注意”标签,让它在并发环境下表现得更好。

       首先,小黑给大家强调一下,volatile主要解决的是可见性问题。可见性,就像它字面上的意思,确保当一个线程修改了volatile变量的值时,其他线程能够立即知道这个改变。这听起来很简单,但在并发编程中,这个特性非常重要。为什么呢?因为在多线程环境中,每个线程可能在自己的工作内存中保留了变量的副本,这就导致了一个线程对变量的修改,其他线程不一定能立即看到。

       下面小黑用一个小例子来展示volatile的使用。假设有一个简单的场景,我们有一个标志位变量,控制着一个线程的运行状态:

       在这个例子中,flag变量被声明为volatile。这意味着,当stopThread方法被调用,将flag设置为true时,正在运行的线程会立即看到这个改变,并退出while循环。

       volatile是Java并发编程中一个非常有用的工具,尤其是在处理可见性问题时。但是它并不是万能的,有它的局限性。

       最后,通过这些例子,咱们可以看到volatile在实际编程中的应用场景。它是一个强大的工具,但要记住它的局限性和合适的使用场景。咱们在编写并发程序时,应该根据具体需求选择合适的同步机制。