Java多线程——从内存模型角度理解原子性问题和可见性问题

一、从操作系统角度理解程序、进程、线程

1.1 强烈推荐两篇博文,阐述的是Linux的程序、进程、线程的内存使用

Linux从程序到进程:www.cnblogs.com/vamei/archi…

Linux并发与同步:www.cnblogs.com/vamei/archi…

1.2 下图是Java中多线程在内存中的分布。建议先看上面两篇文章,写的很好所以直接推荐。

Heap(堆)是一个进程中的所有线程共享的,用于存储动态变量;每创建一个线程,就会给这个线程分配一个栈,Thread栈是线程独有的,一个线程无法访问其他线程栈(局部变量存储在栈中)。

1.3 下图为Java的堆和栈中的对象存储位置

二、多线程原子性问题和内存可见性问题

2.1 Java内存模型与硬件模型

2.2 原子性问题和可见性问题

         内存可见性问题,从2.1中的内存模型与硬件模型可知,每个CPU都有自己的寄存器(CPU Registers)以及缓存(CPU Cache Memmory),线程的运行硬件是CPU,一个线程操作主内存的数据时,先从主内存中读取数据,CPU进行运算,但是运算结束后,有可能并不会将数据存入主内存(RAM-Main Memory),这样其他线程降无法看到数据的变化,这就导致了内存可见性问题。
         原子性问题,如图中的Race Condition那张图,count是一个共享的可变变量,左边的线程和右边的线程对count的操作都是count+1,这个操作分为三个步骤:读取count的值→count+1→存储count。左线程在读取了count的值为1后,正在做count+1时,右线程读取的count值仍然为1,右线程也做了count+1,但也是1+1,这样当两个线程做完三个步骤后,count是2并不是3,这样就引入了原子性问题。这样的三个步骤应该以原子的方式进行(即在这三个步骤运行过程中,不能有其他操作),这样的操作也叫 复合操作

猜你喜欢

转载自juejin.im/post/5d7760ea5188250a9858240f
今日推荐