1. 工作内存和主内存
- 所有的变量都存在主内存中(一份)
- 每个线程有自己独立的工作内存(主内存中该变量的一份拷贝)
2. 可见性和共享变量
- 可见性:一个共享变量的值能够及时地被其他线程看到
- 共享变量:如果一个变量在多个线程的工作内存中都存在拷贝,那么它就是这几个线程的共享变量
下图可以反映以上说明:
3. 约束
- 线程对共享变量的操作只能在自己的工作内存中进行,不能直接修改主内存
- 不同线程之间无法访问其他线程工作内存中的变量,必须通过主内存来访问其他线程工作内存中的变量
4. 共享变量可见性的原理
线程1对工作内存1的修改能及时让线程2及时可到,就是可见了。
4.1 可见性的步骤
- 将工作内存1中更新后的值写入主内存
- 主内存将最新的共享变量的值写入工作内存2
4.2 保证可见性的必要条件
- 工作内存更新的共享变量值要及时写入主内存
- 主内存及时更新共享变量的值写入工作内存2
synchronized实现可见性
5.1 synchronized实现的内容
- 原子性(同步)
- 可见性
5.2 JMM关于synchronized 的规定
- 解锁前必须把工作内存最新值写入主内存
- 加锁前清空工作内存的共享变量值,从主内存更新最新值
5.3 synchronized互斥代码的过程
- 获得互斥锁
- 清空工作内存
- 从主内存拷贝最新变量复制到自己的工作内存
- 执行代码
- 将更改的共享变量值写入主内存
- 释放互斥锁
6 volatile实现可见性
首先在说volatile实现可见性方法之前说一下编译重排序
6.1 重排序
编译器或处理器为了提高性能做优化,调整了执行顺序使得和书写顺序不同
6.2 as if serial语义
无论如何排序,程序执行结果与代码按照书写顺序执行的结果一致。在单线程情况下,遵循as if serial语义
volatile通过内存屏障和禁止重排序优化来实现可见性
- 写操作后加入store屏障指令:写之后强行将更新的值写入主内存
- 读操作前加入load屏障指令:读之前及时从主内存更新最新值
6.3 volatile无法实现原子性
- 一般来说自增操作无法保证其原子性
解决方案:
- 同步块
- ReentrantLock(java.util.concurrent.locks) 3.AtomicInteger(java.util.concurrent.atomic)
多线程中安全使用volatile需要同时满足以下2点
- 对变量的写入操作不依赖当前值(比如自增、自减等操作;)
- 不能包含在一个不变式中(比如low<up,永远成立的)
7 synchronized和volatile的比较
- volatile不需要加锁,更加轻量级,不会阻塞线程
- 从内存可见性角度,volatile变量读等价于加锁,写等价于解锁
- synchronized可以同时保证原子性和可见性,而volatile一般来说只能保证可见性
- volatile需要注意使用的风险
- volatile仅能使用在变量级别,synchronized则可以使用在变量,方法.
- volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化 原文地址:http://blog.csdn.net/uniquewonderq/article/details/48477265
相关推荐
本资源涵盖了Java并发编程的理论基础和实践,主要包括可见性、原子性和有序性的详细介绍,以及多线程的使用原因、好处和坏处等方面的内容。 Java并发编程是一种高效的编程技术,通过多线程实现将计算过程中不必要的...
深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发可见性、有序性、原子性与JMM内存模型深入理解并发...
原子性有序性可见性
可见性可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就这这个操作同样存在线程安
如果应场景需要个更范围的原性保证,Java内存模型还提供了lock和unlock操作来满这种需求,尽管虚拟机未把lock与unlock操作直接开放给户使,但是却
并发二:原子性、可见性、有序性
14、深入理解井发可见性、有序性、原子性与JMM内存模型 (1).pdf 15、CPU缓存架构详解&高性能内存队列Disruptor 实战 (1).pdf 16、常用并发设计模式精讲 (1).pdf designpattern.zip disruptor.zip forkjoin.zip jmm(1...
主要介绍了java 并发中的原子性与可视性实例详解的相关资料,原子性是说一个操作是否可分割。可见性是说操作结果其他线程是否可见。需要的朋友可以参考下
1. 过期数据 2. 锁的可见性 4. 原变量 1. JSL 第三版 2. Java Concurrency in Practice
那么这篇文章就先解决其中的可见性和有序性问题,引出了今天的主角:Java内存模型(面试并发的时候会经常考核到) 什么是Java内存模型? 现在知道了CPU缓存导致可见性、编译优化导致了有序性问题,那么最简单的方式...
1、保证内存可见性 2、防止指令重排 此外需注意volatile并不保证操作的原子性。 (一)内存可见性 1 概念 JVM内存模型:主内存和线程独立的工作内存 Java内存模型规定,对于多个线程共享的变量...
锁不仅保证原子性还保证可见性 有序性 多个线程操作共享对象导致的状态不一致问题 原因 共享资源的竞态条件问题 问题 竞态条件 指令重排序 工作内存中主内存同步延迟 解决 要有安全策略文档或注释 不共享...
在上一篇文章02Java如何解决可见性和有序性问题当中,我们解决了可见性和有序性的问题,那么还有一个原子性问题咱们还没解决。在第一篇文章01并发编程的Bug源头当中,讲到了把一个或者多个操作在 CPU 执行的过程中不...
java多线程的通讯共享数据就是共享内存,共享内存主要有可见性和有序原子性。java 内存原型JMM解决可见有序,线程锁synchronized所解决它的原子性。 JMM内存原型:java可以在不同操作系统不同硬件存储逻辑下运行的...
java面试题_java-interview-questions-...2、 缓存导致的可见性问题 解决办法:synchronized、volatile、LOCK,可以解决可见性问题 3、 编译优化带来的有序性问题 解决办法:Happens-Before 规则可以解决有序性问题
解决并发问题,我们一般需要从原子性、可见性和有序性三方面入手,借助Java关键字及各种同 步工具类来实现。 原子性、可见性、有序性三特性: 1. 原子性:原子性就是说一个操作不能被打断,要么执行完要么不执行。 2...
3.1.3 加锁与可见性 3.1.4 Volatile变量 3.2 发布与逸出 3.3 线程封闭 3.3.1 Ad-hoc线程封闭 3.3.2 栈封闭 3.3.3 ThreadLocal类 3.4 不变性 3.4.1 Final域 3.4.2 示例:使用Volatile类型来发布不可变对象...
o可见性 :一个线程对共享变量的修改,另一个线程能立刻看到。 缓存 可导致可见性问题。 o原子性 :一个或多个CPU执行操作不被中断。 线程切换 可导致原子性问题。 o有序性 :编译器优化可能导致指令顺序发生...
内存屏障的重要性在于,它可以解决多线程程序中的一些问题,如可见性、原子性和顺序性问题。当多个线程访问共享资源时,内存屏障可以确保这些线程按照正确的顺序执行操作,从而避免了数据不一致和线程安全问题。 三...
1、"上海某大厂面试真题,掌握并发编程三大核心—原子性、可见性和有序性,是优化高并发系统性能的关键所在。#Java并发编程 #电商技术挑战" 2、“了解多线程创建的四种方式,包括Runnable、Callable以及线程池的...