JVM保证线程安全
Java内存模型中,程序(进程)拥有一块内存空间,可以被所有的线程共享,即MainMemory(主内存);而每个线程又有一块独立的内存空间,即WorkingMemory(工作内存)。普通情况下,当线程需要对某一共享变量进行修改时,通常会进行如下的过程:
1. 从主内存中拷贝变量的一份副本,并装载到工作内存中;
2. 在工作内存中执行代码,修改副本的值;
3. 用工作内存中的副本值更新主存中的相关变量值。
如下图:
所谓“线程安全”,即多个线程同时执行同一段代码时,不会出现不确定的或者与单线程条件下不一致的结果。通常,下列三种条件居其一的并发访问被JVM认为是线程安全的:
1. 有final关键字修饰且已被赋值;
2. 有volatile关键字修饰;
3. 有锁保护(synchronized、ReentrantLock等)。
第1点显而易见,不再赘述。
volatile关键字的作用是告知JVM:它所修饰的域的原子操作都不需要经过线程的工作内存,而直接在主内存中进行修改。这样就保证了线程从主内存中读取(read)它的值的时候,总是最新的。但是,Java中的运算极少是原子的,即便是像++ 这样的一元运算符或者+= 这样的二元运算符都不是原子的,因此volatile关键字修饰的域在多线程环境下依然可能会读写出“脏”数据:它只保证每一步原子操作的线程安全,但不保证整个操作过程的线程安全。也因此,volatile主要被用于变量只有原子操作的场合,如赋值、移位等。
锁,无论是显式(ReentrantLock)还是隐式(synchronized)的同步锁,或是信号量(Semaphore),抑或是阻塞队列(BlockingQueue),还是其它的同步措施(CyclicBarrier、CountDownLatch、wait¬ify等),它们的作用都是一样的,就是保证一个共享变量的副本进入到某个线程的工作内存之后,该共享变量就不再会被其它线程访问到,直到前述过程的第3步执行完成。
线程在有同步锁的情况下访问共享变量的过程如下:
1. 获取同步锁
2. 清空工作内存
3. 从主内存将拷贝变量副本,并装载到工作内存
4. 对副本执行代码
5. 用副本数据更新主内存中的相关变量
6. 释放同步锁
通常,没有获得同步锁的线程将被阻塞,直到它竞争到同步锁。这样,没有获得同步锁的线程不仅不能访问数据,甚至都不能继续运行,于是强迫性地保证了线程安全。也因此,线程安全代码的开销要大于不安全的代码,同步锁的开销也要大于volatile。
JVM保证线程安全的更多相关文章
- JVM 进行线程同步背后的原理
前言 所有的 Java 程序都会被翻译为包含字节码的 class 文件,字节码是 JVM 的机器语言.这篇文章将阐述 JVM 是如何处理线程同步以及相关的字节码. 线程和共享数据 Java 的一个优点 ...
- 在JAVA中ArrayList如何保证线程安全
[b]保证线程安全的三种方法:[/b]不要跨线程访问共享变量使共享变量是final类型的将共享变量的操作加上同步一开始就将类设计成线程安全的, 比在后期重新修复它,更容易.编写多线程程序, 首先保证它 ...
- ASP.NET MVC Filters 4种默认过滤器的使用【附示例】 数据库常见死锁原因及处理 .NET源码中的链表 多线程下C#如何保证线程安全? .net实现支付宝在线支付 彻头彻尾理解单例模式与多线程 App.Config详解及读写操作 判断客户端是iOS还是Android,判断是不是在微信浏览器打开
ASP.NET MVC Filters 4种默认过滤器的使用[附示例] 过滤器(Filters)的出现使得我们可以在ASP.NET MVC程序里更好的控制浏览器请求过来的URL,不是每个请求都会响 ...
- 灵魂拷问:Java对象的内存分配过程是如何保证线程安全的?(阿里面试)
JVM内存结构,是很重要的知识,相信每一个静心准备过面试的程序员都可以清楚的把堆.栈.方法区等介绍的比较清楚. 上图,是一张在作者根据<Java虚拟机规范(Java SE 8)>中描述的J ...
- JAVA | Java对象的内存分配过程是如何保证线程安全的?
JAVA | Java对象的内存分配过程是如何保证线程安全的? 专注于Java领域优质技术,欢迎关注 作者 l Hollis 来源 l Hollis(ID:hollischuang) JVM内存结构, ...
- JVM和线程池
本文链接:https://blog.csdn.net/liuwenliang_002/article/details/90074283 ————————————————版权声明:本文为CSDN博主「3 ...
- Java基础图解,JVM,线程,Spring,TCP,SpringMVC等开发体系图解
Java基础图解,JVM,线程,Spring,TCP,SpringMVC等开发体系图解 1.Java虚拟机运行时数据区图 2. 堆的默认分配图 3.方法区结构图 4.对象的内存布局图 5.对象头的Ma ...
- Java并发编程(二)如何保证线程同时/交替执行
第一篇文章中,我用如何保证线程顺序执行的例子作为Java并发系列的开胃菜.本篇我们依然不会有源码分析,而是用另外两个多线程的例子来引出Java.util.concurrent中的几个并发工具的用法. ...
- EF 保证线程内唯一 上下文的创建
1.ef添加完这个对象,就会自动返回这个对象数据库的内容,比如下面这个表是自增ID 最后打印出来的ID 就是自增的结果 2.lambda 中怎么select * var userInfoList = ...
随机推荐
- Redis 集成Spring(spring-data-redis)
Spring-data-redis是spring大家族的一部分,提供了在srping应用中通过简单的配置访问redis服务,对reids底层开发包(Jedis, JRedis, and RJC)进行 ...
- js面向对象小结(工厂模式,构造函数,原型方法,继承)
最近过了一遍尼古拉斯泽卡斯的高级程序设计第三版(红皮书)第六章:面向对象程序设计,现在把总结出来的东西和大家分享一下. 主要内容如下: 1.工厂模式 2.构造函数模式 3.原型模式 4.继承 一.工厂 ...
- Javascript设计模式之装饰者模式详解篇
一.前言: 装饰者模式(Decorator Pattern):在不改变原类和继承的情况下动态扩展对象功能,通过包装一个对象来实现一个新的具有原对象相同接口的新的对象. 装饰者模式的特点: 1. 在不改 ...
- Android第二天
1.从看得见的活动入手 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ...
- extjs底层源码实现继承分析
先说明一下在js中一般的继承是怎么写的 var farther=function(name){ this.name=name }; farther.prototype={ constructor:fa ...
- html5之datalist标签
当我看到这个标签的时候,其实我是很愤怒的.因为我以前实现过这个标签的功能,当时是无比的费劲.什么js库呀,function呀.我靠,统统去屎吧,哥有datalist了.那种感觉就好像自己千辛万苦去追去 ...
- [Q]手动加载菜单方法
一般情况下,安装程序会自动安装依云软件菜单,但可能由于某些原因未能自动安装的话,您可以手动加载菜单,步骤如下: 在AoutCAD命令行输入"CUILOAD",会弹出"加载 ...
- Spring 注解式Aop 入门
首先在spring配置文件中加上 xmlns:aop="http://www.springframework.org/schema/aop" http://www.springfr ...
- js中width,height,left,top计算
①offset 包括了元素的边框和内边距和滚动条 offsetWidth.offsetHeight元素的宽度和高度 offsetLeft .offsetTop元素相对于文档左边和顶部的距离(定位 ...
- CODE[VS]-判断浮点数是否相等-浮点数处理-天梯青铜
题目描述 Description 给出两个浮点数,请你判断这两个浮点数是否相等 输入描述 Input Description 输入仅一行,包含两个浮点数 输出描述 Output Description ...