Java内存模型是保障多线程安全的根基,这里不过认识型的理解总结并未深入研究。

一、什么是内存模型,为什么须要它

Java内存模型(Java Memory Model)并发相关的安全公布,同步策略的规范、一致性等都来自于JMM。


1 平台的内存模型
在架构定义的内存模型中将告诉应用程序能够从内存系统中获得如何的保证,此外还定义了一些特殊的指令(称为内存栅栏或栅栏),当须要共享数据时,这些指令就能实现额外的存储协调保证。
JVM通过在适当的位置上插入内存栅栏来屏蔽在JVM与底层平台内存模型之间的差异。


2 重排序
多个线程同一时候操作同一个变量时,读与写必须保证原子性,否则会出现读取的变量值并非最新改动的等重排序问题。



3 Java内存模型简单介绍
Happens-Before的规则包含:

程序顺序规则。假设程序中操作A在操作B之前,那么在线程中A操作将在B操作之前运行。

监视器锁规则。在监视器锁上的解锁操作必须在同一个监视器上的加锁操作之前运行。

Volative变量规则。对Volative变量的写入操作必须在对该变量的读操作之前运行。

线程启动规则。在线程上对Thread.Start的调用必须在线程中运行不论什么操作之前运行。

线程结束规则。在线程中的不论什么操作都必须在其它线程检測到该线程已结束之前运行,或者从Thread.join中成功返回,或者调用Threas.isAlive时返回false。

中断规则。当一个线程在还有一个线程上调用interrupt时,必须在被中断线程检測到interrupt调用之前运行(通过抛出InterruptedException,或者调用isInterrupted和interrupted)。

终结器规则。对象的构造函数必须在启动该对象的终结器之前运行完毕。

传递性。假设操作A在操作B之前运行,而且操作B在操作C之前运行,则操作A必须在操作C之前运行。



4 借助同步
在类库中提供的其它Happens-Before排序包含:

将一个元素放入一个线程安全容器的操作将在还有一个线程从该容器中获得这个元素的操作之前运行。

在CountDownLatch上的倒数操作将在线程从闭锁上的await方法中返回之前运行。

释放Semaphore许可的操作将在从该Semaphore上获得一个许可之前运行。

Future表示的任务的全部操作将在Future.get中返回之前运行。

向Executor提交一个Runnable或Callable的操作将在任务開始运行之前运行。

一个线程到达CyclicBarrier或Exchanger的操作将在其它到达该栅栏或交换点的线程被释放之前运行。假设CyclicBarrier使用一个栅栏操作,那么到达栅栏的操作将在栅栏操作之前运行,而栅栏操作又会在线程从栅栏中释放之前运行。


二、公布

1 不安全的公布
除了不可变对象以外,使用被还有一个线程初始化的对象通常都是不安全的,除非对象的公布操作是在使用该对象的线程開始使用之前运行。


2 安全的公布

3 安全初始化模式

4 双重检查加锁

三、初始化过程中的安全性


參考资料:

《深入理解Java虚拟机:JVM高级特性与最佳实践》 第五部分 高效并发


《Java并发编程实战》第十六章 Java内存模型 读书笔记的更多相关文章

  1. 《Java并发编程实战》第三章 对象的共享 读书笔记

    一.可见性 什么是可见性? Java线程安全须要防止某个线程正在使用对象状态而还有一个线程在同一时候改动该状态,并且须要确保当一个线程改动了对象的状态后,其它线程能够看到发生的状态变化. 后者就是可见 ...

  2. 《Java并发编程实战》第七章 取消与关闭 读书笔记

        Java没有提供不论什么机制来安全地(抢占式方法)终止线程,尽管Thread.stop和suspend等方法提供了这种机制,可是因为存在着一些严重的缺陷,因此应该避免使用. 但它提供了中断In ...

  3. 《Java并发编程实战》第四章 对象的组合 读书笔记

    一.设计线程安全的类 在设计线程安全类的过程中,须要包括下面三个基本要素:  . 找出构成对象状态的全部变量.  . 找出约束状态变量的不变性条件.  . 建立对象状态的并发訪问管理策略. 分析对象的 ...

  4. 《Java并发编程实战》第六章 任务运行 读书笔记

    一. 在线程中运行任务 无限制创建线程的不足 .线程生命周期的开销很高 .资源消耗 .稳定性 二.Executor框架 Executor基于生产者-消费者模式.提交任务的操作相当于生产者.运行任务的线 ...

  5. 《Java并发编程实战》第十章 避免活跃性危急 读书笔记

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/love_world_/article/details/27635333 一.死锁 所谓死锁: 是指两 ...

  6. java并发编程实战:第六章----任务执行

    任务:通常是一些抽象的且离散的工作单元.大多数并发应用程序都是围绕"任务执行"来构造的,把程序的工作分给多个任务,可以简化程序的组织结构便于维护 一.在线程中执行任务 任务的独立性 ...

  7. 【java并发编程实战】第六章:线程池

    1.线程池 众所周知创建大量线程时代价是非常大的: - 线程的生命周期开销非常大:创建需要时间,导致延迟处理请求,jvm需要分配空间. - 资源消耗:线程需要占用空间,如果线程数大于可用的处理器数量, ...

  8. 《Java并发编程实战》第八章 线程池的使用 读书笔记

    一.在任务与运行策略之间的隐性解耦 有些类型的任务须要明白地指定运行策略,包含: . 依赖性任务.依赖关系对运行策略造成约束.须要注意活跃性问题. 要求线程池足够大,确保任务都能放入. . 使用线程封 ...

  9. 《Java并发编程实战》第十一章 性能与可伸缩性 读书笔记

    造成开销的操作包含: 1. 线程之间的协调(比如:锁.触发信号以及内存同步等) 2. 添加�的上下文切换 3. 线程的创建和销毁 4. 线程的调度 一.对性能的思考 1 性能与可伸缩性 执行速度涉及下 ...

  10. 《Java并发编程实战》第五章 同步容器类 读书笔记

    一.同步容器类 1. 同步容器类的问题 线程容器类都是线程安全的.可是当在其上进行符合操作则须要而外加锁保护其安全性. 常见符合操作包括: . 迭代 . 跳转(依据指定顺序找到当前元素的下一个元素) ...

随机推荐

  1. @produces在spring mvc中是什么意思

    @RequestMapping(value = "/produces", produces = "application/json"):表示将功能处理方法将生产 ...

  2. encode_utf8 把字符编码成字节 decode_utf8解码UTF-8到字符

    encode_utf8 $octets = encode_utf8($string); Equivalent to "$octets = encode("utf8", $ ...

  3. Swift - 使用CATransition制作过渡动画(页面切换转场效果)

    CATransition动画主要在过渡时使用,比如两个页面层级改变的时候添加一个转场效果.CATransition分为两类,一类是公开的动画效果,一类是非公开的动画效果. 1,公开动画效果: kCAT ...

  4. 'datetime.datetime' has no attribute 'datetime'问题

    写python时,用到了日期计算.于是写了datetime.datetime(*d_startTime[0:6])这样的代码. 结果编译不通过,报 'datetime.datetime' has no ...

  5. ASP.NET中IsPostBack详解(转载)

    1.IsPostBack介绍Page.IsPostBack是一个标志:当前请求是否第一次打开. 调用方法为:Page.IsPostBack或者IsPostBack或者this.IsPostBack或者 ...

  6. Eclipse用法和技巧四:生成说明文档1

    写代码经常要添加注释的,java代码的注释也可以分为两种.单行注释以“//”作为开头就可以.段落注释在第一行开头添加“/*”,在最后一行结尾添加“*/"即可.这里介绍一种添加注释的方法,其注 ...

  7. C#中System.Globalization.DateTimeFormatInfo.InvariantInfo怎么用

    原文  C#中System.Globalization.DateTimeFormatInfo.InvariantInfo怎么用 在开发的时候,碰到下面这样一个问题: 在程序中显示当前系统时间,但是有一 ...

  8. 基于visual Studio2013解决C语言竞赛题之1092链表转换

        题目 解决代码及点评 /************************************************************************/ /* ...

  9. access数据库:怎么直接从access里把数据里同样的文字替换成空字符""

    access数据库:怎么直接从access里把数据里同样的文字替换成空字符"" 搜所到文字后,替换的项里写"",就是了.一定要是英文的""

  10. 获取字符宽度:并非自适应。coretext去计算

    获取字符宽度:并非自适应.coretext去计算 UniChar ch = [ns_str characterAtIndex:0]; CGGlyph glyph = 0; CTFontGetGlyph ...