java并发编程的艺术学习笔记-volatile和锁的内存语义

4 篇文章 0 订阅
1 篇文章 0 订阅

volatile的内存语义

volatile写-读的内存语义

volatile写内存定义:当写一个volatile内存变量的时,JMM会把该线程对应的本地内存中的共享变量值刷新到主内存。也就是说当写一个volatile变量的时候,之前共享变量的操作结果要刷新到主内存,之前的操作不能重排序到该操作之后。
volatile读内存定义:当读一个volatile内存变量的时,JMM会把线程对应的本地内存置为无效。线程接下来从内存中读取共享变量。也就是说当读一个volatile变量时,会从内存中加载到本地内存中,之后对共享变量的操作的值要重新获取,之后的操作不能重排序到该操作之前。

总结:当写一个volatile的时候,此操作之前的共享变量的值会被刷新到主内存中,向其它操作该volatile共享变量的线程发出通知。当读一个volatile共享变量的时候,会重新读取共享变量的值,收到消息,读到其它线程修改的共享变量的值,实现共享变量的可见性。

volatile内存语义的实现

编译重排序

下图为重排序规则表

在这里插入图片描述

图表分析
1.当第二个操作是volatile写时,不管第一个操作是什么,都不支持重排序。这个规则确保volatile写之前的操作不会被编译器重排序到volatile之后。
2.当第一个操作是读的时候,不管第二个操作是什么,都不能重排序。这个规则确保volatile读之后的操作不会被编译器重排序到volatile之后。
3.但第一个操作是volatile写,第二个操作是volatile读时,不能重排序。

总结:volatile写操作之前的操作不能重排序到volatile写操作之后(volatile写的内存语义,之前的共享变量操作要刷新到主内存),volatile读操作之后的语句不能重排序到volatile读操作之前(volatile读的内存语义,之后的共享变量操作的值要重新从内存中获取),先volatile写后voilate读可以看做共享变量内存操作的数据依赖不支持重排序,最终实现线程之间操作的可见性。

处理器重排序

1.在每个volatile写操作前插入StoreStore屏障
2.在每个volatile写操作之后插入StoreLoad屏障
3.在每个volatile读操作之后插入一个LoadLoad屏障
4.在每个volatile读操作之后插入一个LoadStore屏障

总结:执行volatile写内存操作时,因为插入StoreStore屏障该操作之前的写内存操作都要先执行,以为之后插入StoreLoad屏障会执行所有的内存操作指令在继续向下执行(volatile写的内存语义);执行volatile读操作时,因为读操作插入LoadLoad屏障和LoadStore屏障,volatile之后的所有内存操作(读和写)不能重排序到该操作之前执行(volatile写操作语义)。

锁的内存语义

锁的释放和获取的内存语义

线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中;线程获取锁时,JMM会把线程对应的本地内存置为无效,从而使得被监视器保护的临界区代码必须从主内存中读取共享变量。

锁内存语义的实现

公平锁通过(AbstractQueuedSynchronizer)AQS,AQS通过修改或读取整型的volatile变量来维护同步状态,非公平锁通过原子操作的compareAndSet方法(CAS)更新state变量实现。

current包实现

  1. 声明共享变量为volatile。
  2. 使用CAS的原子条件更新来实现线程间的同步。
  3. 配合以volatile读/写和CAS锁具备的volatile读写的内存语义来实现线程之间的通行。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值