08 JAVA 线程 内存模型(一)

本文深入探讨了Java内存模型的概念、线程之间的通信机制,包括共享内存、消息传递、线程同步以及内存模型的抽象表示。重点解释了主内存与本地内存的关系、重排序原则以及写缓冲区的作用。同时,阐述了Java内存模型的一致性与顺序一致性模型的区别,并通过实例说明了数据依赖性、as-if-serial规则以及happen-before关系的重要性。

一、介绍

- 线程通信

1. 共享内存 2. 消息传递

- 线程同步

- 内存模型的抽象

实例域,静态域和数据元素存储在内存中,堆内存在线程之间共享,但是局部变量,方法定义参数和异常处理参数不会在线程之间共享。JAVA线程之间的通信由JAVA内存模型(JMM)控制,它可以决定一个线程对共享变量的写入何时对另一个线程可见,即JMM定义了线程和主内存之间的抽象关系:线程之间的共享变量存储在主内存中,每个线程都有一个私有的本地内存,本地内存中存储了该线程以读/写共享变量的副本~本地内存是一个抽象概念,而不是真实存在~


A/B写进主内存,B/A从主内存读取,实质上是通过两个进程之间的消息传递(当AB需要通信,修改线程会先将结果刷到内存中)

- 重排序,为了执行程序时提高性能,编译器和处理器常常会对指令做重排序,三种类型:

1. 编译器优化的重排序,编译器在不改变单线程线程语义的前提下,可以重新安排语句的执行顺序(会禁止某种特定的编译器排序)

2. 处理器重排序,指令以及并行的重排序,将多条指令重叠执行,如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序,在java编译器生成指令序列的时插入特定类型的内存屏障memory barriers,通过它来限制特定类型的处理器重排序

3. 处理器重排序,内存系统的重排序,由于处理器使用缓存和读/写缓冲区,使得加载和存储操作看上去可能是乱序执行的


- 写缓冲区的优点

批写入节省时间,合并写操作,避免对同一个内存地址多次写,减少对内存总线的占用,而且对于回滚也是有好处的。但是,写缓冲区只对它所在的处理器可见,处理器的执行顺序,不一定和内存实际发生的顺序一致(就是当写入的数据还未被刷入主内存中,主内存中的旧数值被读取)

- 重排序需要考虑因素(都是针对单线程)

1. 数据依赖性,针对单个处理器中执行的质量顺序,不同处理器之间和不同线程之间的数据依赖性不被考虑

举例:

1a = 1;

2b = a;

第二句依赖于第一句,所以不能被重排序

2. as-if-serial,不管怎么排序,程序的执行结果不能被改变~

举例:

1double pi = 3.14;

2int a = 3;

3double area = a * pi;

然而调换第一句和第二句的位置并不影响程序的执行结果

- happen-before关系,JMM中,仅仅要求前一个操作的执行结果对后面一个操作可见即可

1. 程序顺序规则,一个线程中中的每个操作

2. 监视器锁规则

3. volatile变量规则

4. 传递性

二、一致性内存模型

- 一个线程中的所有操作必须按照程序的顺序来执行

- 所有线程都只能看到一个单一的操作执行顺序(就是不同时刻不同的线程执行时,看见的是一样的操作执行顺序)

1. JMM表示如果是正确同步的,程序的执行将具有一致性,而未同步的程序在JMM中不但整体的执行顺序是无序的,而且所有线程看到的操作执行顺序也可能不一致

2. 顺序一致性模型中,所有操作完全按程序的顺序串行执行,而在JMM中,临界区内的代码可以重排序(JMM不允许临界区内的代码溢出临界区之外,里面的语句必须在进入临界区和退出临界区之间发生)

class SynchronizedExample {

int a = 0;

boolean flag = false;

public synchronized void writer() {

a = 1;

flag = true;

}

public synchronized void reader() {

if(flag) {

int i = a;

}

}

3. JMM不保证对64位的long位和double型变量的读/写操作具有原子性

总线事务:处理器与内存之间的数据传递,包括读事务和写事务。一个处理器执行总线事务期间,总线会禁止其他所有的处理器和I/O设备执行内存的读/~

在一个32位的处理器上,如果要求对64位数据的写操作具有原子性,会有比较大的开销。因为一般是把一个64位数据拆分成两个32位写操作来执行,而这两个写操作可能会被分配到不同的总线事务中执行,此时对这个64位变量的写将不具原子性


4. 控制依赖关系

为了提高控制逻辑block的执行速度,编译器和处理器会采用猜测执行,对于单线程并不会改变执行结果,而对于多线程,语义就被破坏了,需要我们的同步

Reference:

1. 深入理解JAVA内存模型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值