关于volatile关键字的一些个人理解

前言

众做周知,JAVA语言做并发编程最适合不过了,而且提供了众多的关键字来保证在高并发下程序性的稳定性,syschronized和volatile都是一种锁的机制,但是有syschronized为什么还要有volatile呢??其实,关键点就在于,性能问题

谈这个关键字,主要还是要从下面几点讲起

 一、内存模型的相关概念      

二、并发编程中的三个概念  

  三、深入剖析volatile关键字

 四、使用volatile关键字的场景  

  五、synchronize与volatile的区别

一、内存模型的相关概念

(1)不同的平台,内存模型是不一样的,但是jvm的内存模型规范是统一的       

(2)线程安全无非是要控制多个线程对某个资源的有序访问或修改。总结java的内存模型多线程下,要解决两个主要的问题:可见性和有序性。          

(3)我们都知道计算机有高速缓存的存在,处理器并不是每次处理数据都是取内存的。JVM定义了自己的内存模型,屏蔽了底层平台内存管理细节

内存模型的工作原理

线程执行的时候,将首先从主内存读值,再load到工作内存中的副本中,

然后传给处理器执行,执行完毕后再给工作内存中的副本赋值,

随后工作内存再把值传回给主存,主存中的值才更新

 二、并发编程中的三个概念

1、原子性

只有简单的读取、赋值(而且必须是将数字赋值给某个变量,变量之间的相互赋值不是原子操作)才是原子操作

当然,以下这些都是原子性操作,有兴趣的可以自行了解

LOCK(锁定),UNLOCK(解锁),read(读),load(载入),use(使用), assign(赋值),store(存储),write(写入)

2、可见性

多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值

3、有序性

在Java内存模型中,允许编译器和处理器对指令进行重排序,(JIT认为可以优化下就给你改变了执行顺序)

但是重排序过程不会影响到单线程程序的执行,却会影响到多线程并发执行的正确性

三、volatile关键字

Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。

当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,

因此不会将该变量上的操作与其他内存操作一起重排序

volatile变量不会被缓存在寄存器或者对其他处理器不可见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。

一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:

1、 保证多线程下的可见性 2、 禁止进行指令重排序(即保证有序性)。

四、volatile使用前提

1、对变量的写操作不依赖于当前值

2、该变量没有包含在具有其他变量的不变式中 简单来说,就是保证该操作是原子性操作

五、volatile的使用场景

1、volatile bean 模式 

volatile bean 模式适用于将 JavaBeans 作为“荣誉结构”使用的框架。在 volatile bean 模式中,JavaBean 被用作一组具有 getter 和/或 setter 方法 的独立属性的容器。volatile bean 模式的基本原理是:很多框架为易变数据的持有者(例如 HttpSession)提供了容器,但是放入这些容器中的对象必须是线程安全的。

在volatile bean 模式中,JavaBean 的所有数据成员都是 volatile 类型的,并且 getter 和 setter 方法必须非常普通 —— 除了获取或设置相应的属性外,不能包含任何逻辑。此外,对于对象引用的数据成员,引用的对象必须是有效不可变的。(这将禁止具有数组值的属性,因为当数组引用被声明为 volatile 时,只有引用而不是数组本身具有 volatile 语义)。对于任何 volatile 变量,不变式或约束都不能包含 JavaBean 属性

2、开销较低的读-写锁策略

之所以将这种技术称之为 “开销较低的读-写锁” 是因为您使用了不同的同步机制进行读写操作。因为本例中的写操作违反了使用 volatile 的第一个条件,因此不能使用 volatile 安全地实现计数器 —— 您必须使用锁。然而,您可以在读操作中使用 volatile 确保当前值的可见性,因此可以使用锁进行所有变化的操作,使用 volatile 进行只读操作。其中,锁一次只允许一个线程访问值,volatile 允许多个线程执行读操作,因此当使用 volatile 保证读代码路径时,要比使用锁执行全部代码路径获得更高的共享度 —— 就像读-写操作一样。然而,要随时牢记这种模式的弱点:如果超越了该模式的最基本应用,结合这两个竞争的同步机制将变得非常困难。

synchronized和volatile的异同

java中能创建volatile数组吗?

如果将volatile修饰在数组上,它只对引用这个数组的属性本身有效,而对这个数组里面引用的对象,是没有效果的

转载请注明出处,掌声送给社会人

猜你喜欢

转载自blog.csdn.net/SCDN_CP/article/details/84839877