Java并发编程实战

最近在看java并发编程实战,打算记录一些自己认为经常面试用的知识点。


1.Volatile变量

1.1 作用:它用来确保将变量的更新操作通知到其他线程。
volatile可以保证线程可见性且提供了一定的有序性,但是无法保证原子性。
1.保证可见性、不保证原子性
2.禁止指令重排序
可见性的实现:
(1)修改volatile变量时会强制将修改后的值刷新的主内存中。
(2)修改volatile变量后会导致其他线程工作内存中对应的变量值失效。因此,再读取该变量值的时候就需要重新从读取主内存中的值。
有序性的实现:
volatile限制操作系统进行指令重排序(编译器重排序和处理器重排序)。而实现volatile可见性和happen-befor的语义是由JVM通过一组叫做内存屏障的处理器指令完成的,它可以实现对内存顺序的限制。
对于原子性:
volatile只能保证读/写操作单个的原子性,如果一个操作包含了读和写之类的复合操作,volatile不能保证其原子性。

1.2 Volatile变量是比锁更加轻量级的一种同步机制。
线程在访问volatile变量的时候不会执行加锁操作,所以也不会执行线程阻塞,因此volatile是一种比synchronized更加轻量级的同步机制。

1.3volatile变量对可见性的影响比volatile变量本身更加重要。
当线程A首先写入一个volatile变量并且线程B随后读取到了该变量后,对写入volatile变量之前对A可见的所有变量值,在B读取了volatile变量后。对B也是可见的。从内存可见的角度来看,写入volatile变量相当于推出同步代码块,而读取volatile变量就相当于进入同步代码块。

1.4使用volatile变量的条件
(1)对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值;
(2)该变量不会与其他状态变量一起纳入不变性条件中;
(3)在访问变量时不需要锁。
比如在第一个条件中,遇到要保证递增操作(i++)的原子性时候,就不能只靠使用volatile变量,因为volatile只能确保可见性,不能确保原子性。
对于第二个条件,如果程序中要求保存当前的值和上一个值,如果都用volatile变量修饰,就有两个volatile变量。但是在保存当前的值的时候,不能原子性地保存上一个值,这样就会造成在保存这两个值的间隙可能会被其他线程修改值,产生程序不正常运行。


2.JVM内存模型

这里写图片描述
Java内存模型将内存分为了 主内存和工作内存 。类的状态,也就是类之间共享的变量,是存储在主内存中的,每个线程都有一个自己的工作内存(相当于CPU高级缓冲区,这么做的目的还是在于进一步缩小存储系统与CPU之间速度的差异,提高性能),每次Java线程用到这些主内存中的变量的时候,会读一次主内存中的变量,并让这些内存在自己的工作内存中有一份拷贝,运行自己线程代码的时候,用到这些变量,操作的都是自己工作内存中的那一份。在线程代码执行完毕之后,然后在某个时间点上再将最新的值更新到主内存中去。
这样导致的问题是,如果线程1对某个变量进行了修改,线程2却有可能看不到线程1对共享变量所做的修改。


JMM java内存模型

猜你喜欢

转载自blog.csdn.net/FateRuler/article/details/82531301