文章目录
- Java内存模型的基础
- 并发编程模型的两个关键性问题
- 1、线程之间如何通信?(问题1)
- 2、进程之间如何通信?(问题2)
- 线程间通信机制:共享内存、消息传递
- 1、共享内存
- 2、消息传递
- java内存模型抽象结构
- 指令重排序
- 并发编程模型的分类
- happens-before
——————————————————————————————————
Java内存模型的基础
并发编程模型的两个关键性问题
1、线程之间如何通信?(问题1)
- t1改的东西,t2能够读到它
- 两个线程能够操作同一个地方,一个线程修改了变量,另一个线程能够读到
2、进程之间如何通信?(问题2)
- 进程间通信是一组编程接口,让程序员能够协调不同的进程,使之能在一个操作系统里同时运行,并相互传递、交换信息。
- 这使得一个程序能够在同一时间里处理许多用户的要求。
- 因为即使只有一个用户发出要求,也可能导致一个操作系统中多个进程的运行,进程之间必须互相通话。
- —>IPC接口就提供了这种可能性。
- 每个IPC方法均有它自己的优点和局限性,一般,对于单个程序而言使用所有的IPC方法是不常见的。
进程间通信的8种方法:
1)无名管道通信
2)高级管道通信
3)有名管道通信
4)消息队列通信
5)信号量通信
6)信号
7)共享内存通信
8)套接字通信
注: - 线程有的通信方式进程不一定有
- 进程有的通信方式线程一定有
- 因为进程是由线程组成的
线程间通信机制:共享内存、消息传递
1、共享内存
- 同一个进程里的线程,能共享堆里面的对象(共享空间);
- 不同进程之间,内存不共享
- 有自己主方法的都是一个进程,有自己的独立空间,空间不共享;
- t1进程不能读取t2进程的变量
2、消息传递
——》通过方法调用
java内存模型抽象结构
- 每个线程都有一个本地的副本
- 线程a要想给线程b通信依托共享变量
- 如果线程A与线程B之间要通信的话,必须要经历下面2个步骤。
- 1)线程A把本地内存A中更新过的共享变量刷新到主内存中去。
- 2)线程B到主内存中去读取线程A之前已更新过的共享变量。
静态的句柄在方法区,静态的值伴随句柄存在
静态引用类型的值在堆中
- 如果线程A与线程B之间要通信的话,必须要经历下面2个步骤。
指令重排序
- 依托于计算机组成原理的流水线技术,是由流水线技术导致的
- 为了提高性能,编译器和处理器常常会对指令做重排序:
重排序分为三种:
- 编译器优化的重排序
- 编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序
- 指令级并行的重排序
- 现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序。
- 内存系统的重排序
- 由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
- 由于处理器使用缓存和读/写缓冲区,这使得加载和存储操作看上去可能是在乱序执行。
并发编程模型的分类
讲的重排序导致的结果
- 两行代码——》a = 1; b = 2;有可能是后面的代码先执行(指令重排序)
- 一行代码——》Object a = new Object();可能是先开辟空间再创建对象。一行代码的执行顺序也有可能是乱序的(比如先有了对象的地址,对象还不存在)
两个线程共同操作a,b,x,y
结果x=y=0出现的原因是x=b;y=a;先执行了。
读写操作:
- a = b;等号右侧是变量为读操作
- a = 8;等号右侧是值为写操作
读写四种组合: - (Load-Load)读-读:a = b; c = d;
- (Load-Store)读-写:a = b; e = 9;
- (Store-Store)写-写:w = 8; q = 5;
- (Store-Load)写-读:r = 8; h = g;
认为:有数据依赖不能重排序,其他时候都能重排序。(有数据依赖的情况=> a=2; b=a;)
内存屏障类型:
通过某种手段防止指令重排序——>保障写后读
保障写后读就是保障多线程下的安全(基于其他线程计算的结果上去计算)
happens-before
在JMM中,如果一个操作执行的结果需要对另一个操作可见,那么这两个操作之间必须要存在happens-before关系。
- 程序顺序规则: 一个线程中的每个操作,happens-before于该线程中的任意后续操作。
- 监视器锁规则:对一个锁的解锁,happens-before于随后对这个锁的加锁。
- ⭐volatile变量规则:对一个volatile域的写,happens-before于任意后续对这个volatile域的读。 (小面试点)
- ⭐传递性:如果A happens-before B,且B happens-before C,那么A happens-before C。 (面试点)
两个操作之间具有happens-before关系,并不意味着前一个操作必须要在后一个操作之前执行!
【happens-before仅仅要求前一个操作(执行的结果)对后一个操作可见,且前一个操作按顺序排在第二个操作之前】