Java并发编程的艺术笔记(三)

3. Java内存模型

1. Java内存模型基础

1. 并发编程两个关键性问题

线程之间如何通信:

通信是指线程之间如何交换数据。通信机制有两种:共享内存和消息传递。

修改共享内存的是隐式通信,而消息传递没有公共状态,为显示传递。

线程之间如何同步:

通信和同步是相同的。

2. Java内存模型抽象结构

Java内存模型要结合JVM来看,线程共享的是堆内存和方法区,私有的是程序计数器,虚拟机栈和本地方法栈。

线程和主存之间有本地内存,存储着共享变量的副本。两个线程通信,就需要将另一个线程更新的数据重新更新到本地内存的副本中。

线程间的通信需要经过主存,线程1修改的值会先存储在本地内存中。当线程1与线程2需要通信,线程1将值写回到主存,然后线程2更新。

3. 指令重排序
  • 编译器优化的重排序
  • 指令集并行的重排序
  • 内存系统的重排序

指令重排序为的是提高CPU的执行效率,volatile会禁止指令重排序。但是volatile只能保证一致性和可见性,对于复杂操作不保证原子性操作(volatile++类似的操作)。

4. happens-before

2. 重排序

编译器和处理器为了优化程序性能而对指令进行的重新排序。

1. 数据依赖行

数据依赖三种形式:读后写、写后写、写后读。

2. as-if-serial语义

不管怎么重排序,程序执行的结果不能被改变。编译器、runtime、处理器必须满足。

3. volatile内存语义

volatile的写锁的释放;volatile的读锁的获取

当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量更新到主存中。

4. 锁的内存语义

锁可以让临界区互斥执行,还可以让释放锁的线程向获得同一个锁的线程发送消息。

1. intel中lock命令
  1. 确保内存中读改写操作原子性执行。
  2. 禁止该命令与之前,之后的命令进行指令重排序。
  3. 把写缓冲区中的所有数据刷新到内存中。

Java线程之间的通信有4四种:

  1. 线程A写volatile变量,线程B读volatile变量
  2. 线程A写volatile变量,线程B用CAS更新volatile变量
  3. 线程A用CAS更新volatile变量,线程B读volatile变量
  4. 线程A用CAS更新volatile变量,线程B用CAS更新volatile变量
2. AQS

AQS是一种提供了原子式管理同步状态、阻塞和唤醒线程功能以及队列模型的简单框架。

非阻塞数据结构和原子变量类。

下面是concurrent包下实现的示意图

在这里插入图片描述

5. final域

1. final域重排序的规则
  • 在构造函数内赋值的final与随后把这个对象引用赋值给一个引用变量,这两个操作之间不能重排序。
  • 初次读这个final域的对象的引用与初次读这个final域,这两个操作不能重排序。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值