Java多线程学习笔记之三内存屏障与Java内存模型
基本内存屏障
处理器支持那种内存重排序,就会提供能够禁止相应内存重排序的的指令,这些指令就被成为基本内存屏障:StroeLoad屏障、StroeLoad屏障、LoadLoad屏障、LoadStore屏障。基本内存屏障是对一类指令的称呼(可以用XY来标识),这类指令的作用是禁止该指令左侧的X操作与该指令右侧的Y操作之间进行重排序,从而确保该指令左侧的所有X操作先于该指令右侧的Y操作被提交,即内存操作作用到主内存(或高速缓存)上。基本内存屏障只是保障其左侧的X操作先于右侧的Y操作被提交,但是它并不完全禁止重排序,XY屏障两侧的内存操作仍然可以在不越过内存屏障本身的情况下在各自范围内进行重排序,并且XY屏障左侧的非X操作和屏障右侧的非Y操作之间仍可以重排序。
基本内存屏障的具体作用
屏障名称 | 示例指令序列 | 具体作用 |
StroeLoad |
Store1,Store2,Store3, StoreLoad,Load1,Load2,Load3 |
禁止StoreLoad重排序,即确保该屏障之前的任何一个写操作的结果都会在该屏障之后任何一个读操作的数据被加载之前对其他处理器来说是可同步的 |
StoreStore |
Store1,Store2,Store3, StoreStore,Store4,Store5,Store6 |
禁止StoreStore重排序,即确保该屏障之前的任何一个写操作的结果都会在该屏障之后任何一个写操作之前对其他处理器来说是可同步的 |
LoadLoad |
Load1,Load2,Load3, LoadLoad,Load4,Load5,Load6 |
禁止LoadLoad重排序,即确保该屏障之前的任何一个读操作的数据都会在该屏障之后的任何一个读操作之前被加载 |
LoadStore |
Load1,Load2,Load3, LoadStore,Store1,Store2,Store3 |
禁止LoadStore重排序,确保该屏障之前的任何一个读操作的数据都会在该屏障之后的任何一个写操作的结果被冲刷到高速缓存(或主内存)之前被加载 |
- StroeLoad 屏障会清空无效化队列,并将写缓冲器中的条目冲刷到高速缓存。因此,StroeLoad 屏障既可以将其他处理器对共享变量所做的更新同步到该处理器的高速缓存中,又可以使其处理器对共享变量所做的共享对其他处理器来说是同步的。
- StoreStore屏障是通过对写缓存器中的条目进行标记来实现禁止StoreStore重排序的。StoreStore屏障会将写缓冲器中的现有条目做一个标记,以表示这些条目代表的写操作需要先于该屏障之后的写操作被提交处理器在执行写操作时如果发现写缓冲器中存在被标记的条目,那么即使这个写操作对应的高速缓存条目的状态为M或E,也不直接写入高速缓存,而是写入写缓冲器,保证StoreStore屏障之前的写操作先于之后的写操作被提交。
- LoadLoad屏障是通过清空无效化队列来实现禁止LoadLoad重排序。LoadLoad屏障会使其执行处理器根据无效化队列中的Invalidate消息删除其高速缓存中相应的副本。是处理器有机会将其他处理器对共享变量所做的更新同步到该处理器的高速缓存中,从而消除了LoadLoad重排序重排序的根源。
Java内存模型
Java内存模型定义了final、volatile、synchronized关键字的行为,并确保正确同步的Java程序能够正确的运行在不同架构的处理器上。它从“什么”的角度解答了以下几个线程安全问题。
- 原子性问题:针对实例变量、静态变量(即共享变量非局部变量)的读、写操作,哪些是具备原子性的,哪些可能不具备原子性。
- 可见性问题:一个线程对实例变量、静态变量进行的更新在什么情况下能够被其他线程所读取。
- 有序性问题:一个线程对多个实例变量、静态变量进行的更新在什么情况下在其他线程看来可以是乱序的。
在原子性方面,Java内存模型规定了对long、double型以外的基本数据类型和引用数据类型的共享变量进行读、写操作都是具有原子性的。特别的,对于volatile修饰的long、double型共享变量进行读、写操作也是具有原子型的。可见性和有序性,Java内存模型是通过happens-before这个术语解答的。
happens-before关系
假设动作A happens-before 动作B,那么Java内存模型机会保证A的操作结果对B是可见的,即A的操作结果会在B被执行请提交。happens-before关系具有传递性,如果A happens-before B,B happens-before C,则A happens-before C。Java内存模型定义了一些有关happens-before关系的规则,这些规则规定了两个动作在什么情况下具有happens-before关系,如下所示。
- 程序顺序规则:一个线程中每个动作都happens-before该线程中程序顺序上排在该动作之后的每一个动作。
- 内部锁规则:内部锁的释放happens-before后续每一个对该锁的申请。释放和申请必须是针对同一锁实例。
- volatile变量规则:对一个volatile变量的写操作happens-before后续每一个对该变量的读操作。
- 线程启动规则:调用一个线程的start方法happens-before被启动这个线程中的任何一个动作。
- 线程终止规则:一个线程中任何一个动作都happens-before该线程的join方法的执行线程在join方法返回之后所执行的任意一个动作。
Java多线程学习笔记之三内存屏障与Java内存模型的更多相关文章
- java多线程学习笔记——详细
一.线程类 1.新建状态(New):新创建了一个线程对象. 2.就绪状态(Runnable):线程对象创建后,其他线程调用了该对象的start()方法.该状态的线程位于可运行线程池中, ...
- JAVA多线程学习笔记(1)
JAVA多线程学习笔记(1) 由于笔者使用markdown格式书写,后续copy到blog可能存在格式不美观的问题,本文的.mk文件已经上传到个人的github,会进行同步更新.github传送门 一 ...
- Java多线程学习笔记(一)——多线程实现和安全问题
1. 线程.进程.多线程: 进程是正在执行的程序,线程是进程中的代码执行,多线程就是在一个进程中有多个线程同时执行不同的任务,就像QQ,既可以开视频,又可以同时打字聊天. 2.线程的特点: 1.运行任 ...
- Java多线程学习笔记
进程:正在执行中的程序,其实是应用程序在内存中运行的那片空间.(只负责空间分配) 线程:进程中的一个执行单元,负责进程汇总的程序的运行,一个进程当中至少要有一个线程. 多线程:一个进程中时可以有多个线 ...
- Java多线程学习笔记--生产消费者模式
实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前 ...
- java 多线程学习笔记
这篇文章主要是个人的学习笔记,是以例子来驱动的,加深自己对多线程的理解. 一:实现多线程的两种方法 1.继承Thread class MyThread1 extends Thread{ public ...
- Java 多线程学习笔记:生产者消费者问题
前言:最近在学习Java多线程,看到ImportNew网上有网友翻译的一篇文章<阻塞队列实现生产者消费者模式>.在文中,使用的是Java的concurrent包中的阻塞队列来实现.在看完后 ...
- java多线程学习笔记(七)
volatile关键字 关键字volatile的主要作用是使变量在多个线程间可见. public class PrintString { private boolean isContinue = tr ...
- java多线程学习笔记(四)
上一节讲到Synchronized关键字,synchronized上锁的区域:对象锁=方法锁/类锁 本节补充介绍一下synchronized锁重入: 关键字synchronized拥有锁重入的功能,也 ...
随机推荐
- WPF 中Canvas图形移动、缩放代码
从Flash转C#,很多内容一知半解,边摸索边前进,代码粗糙,权当留个脚印. 只是想得到一个基础的移动和缩放功能的界面,找了很久都是画线.画矩形等基础形状的代码,移动和缩放说的并不清晰,只能自己努力来 ...
- JSON & Ajax
Ajax是异步JavaScript和XML是用来在客户端作为一组相互关联的Web开发技术,以创建异步Web应用程序. Ajax模型,Web应用程序可以发送数据和检索数据从一个服务器,而不干扰现有的页面 ...
- Claim-Based Identity for Windows: Technologies and Scenarios
Claim-Based Identity for Windows: Technologies and Scenarios Active Diretory Federation Services 2.0 ...
- [日常] Go语言圣经-基于select的多路复用习题
练习 8.8: 使用select来改造8.3节中的echo服务器,为其增加超时,这样服务器可以在客户端10秒中没有任何喊话时自动断开连接. reverb3.go package main import ...
- Jquery动态设置下拉框selected --(2018 08/12-08/26周总结)
1.Jquery动态根据内容设置下拉框selected 需求就是根据下拉框的值动态的设置为selected,本以为很简单,网上一大推的方法,挨着尝试了之后却发现没有一个是有用的.网上的做法如下: &l ...
- Logback 日志持久化
Logback是log4j的增强版,比log4j更具灵活,其提供了将日志输出到数据库的功能,本文将介绍如何将指定的日志输出到mysql中. 一.自定义log标志 由于Logback原生的配置会将所有的 ...
- html前端学习
html : 1.相当于没有穿衣服的人,一套浏览器认识的规则, 2.开发者: 学习html规则 开发后台程序: -写html文件(充当模板) -数据库获取数据,然后替换到html文件的指定位置(web ...
- git基础使用——TortoiseGit
一.初识git Git是一个开源的分布式版本控制系统,用于敏捷高效地处理任何或小或大的项目. Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制 ...
- Oracle常用方法备份
1.UNION ALL 和UNION.INTERSECT.MINUS 连接所有的查询结果.去掉重复的结果.操作返回查询结果中公共的行.在进行两个表格或者两个查询结果的时候,返回在第一个表格/查询结果中 ...
- Oracle 修改oracle数据库名
Oracle 修改oracle数据库名 by:授客 QQ:1033553122 1.确保你有个可用于数据库恢复的,完整的数据库备份 2.确保数据库处于mount,非open状态,并且在加载前先以imm ...