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 = ...
随机推荐
- .Net程序员学用Oracle系列(7):视图、函数、过程、包
<.Net程序员学用Oracle系列:导航目录> 本文大纲 1.视图 1.1.创建视图 2.函数 2.1.创建函数 2.2.调用函数 3.过程 3.1.创建过程 3.2.调用过程 4.包 ...
- java 企业网站源码模版 有前后台 springmvc SSM 生成静态化
java 企业网站源码 前后台都有 静态模版引擎, 代码生成器大大提高开发效率 系统介绍 点击:获取地址 : 1.网站后台采用主流的 SSM 框架 jsp JSTL,网站后台采用freemaker静态 ...
- 【CSS学习笔记】初始化CSS后,写li,并利用背景图片,来完成li小图标的效果,且达到个浏览器兼容
第一种情况 /*当标题前的图标时单独的一个点儿或者方块或者其他类似图标时,定义背景图background要放在<li>里. 在<li>中设置背景图片的尺寸,地址,不重复, ...
- maven自定义骨架
Maven 的 archetype 技术,为新建标准化的工程框架提供了方便.为自定义一套工程框架标准,可参考以下步骤操作: 1,创建一个项目的原型 2,在项目根目录执行命令:mvn archetype ...
- .PHP后缀大写导致Linux下Composer找不到类
在本地Windows写完一个Composer包,上传到Linux报错找不到类,纠结了一下午,最后发现是.PHP后缀大写导致的问题. mv Google2FA.PHP Google2FA.php
- 学习笔记之html5相关内容
写一下昨天学习的html5的相关内容,首先谈下初次接触html5的感受.以前总是听说html5是如何的强大,如何的将要改变世界.总是充满了神秘感.首先来谈一下我接触的第一个属性是 input的里面的 ...
- shell 读取文件
#!/bin/bash content=`cat test.txt` echo "begin" for i in $content do echo $i done 读取前10行 t ...
- MyEclipse 代码提示设置
打开 Eclipse -> Window -> Perferences -> Java -> Editor -> Content Assist,在右边最下面一栏找到 au ...
- RubyMine 2016.1 下载 附注册激活码 破解版方法
注册破解方法: 在要求输入注册的界面选择激活码,然后粘贴以下注册码: 43B4A73YYJ-eyJsaWNlbnNlSWQiOiI0M0I0QTczWVlKIiwibGljZW5zZWVOYW1lIj ...
- python1 tkinter
turtle 图形: turtle.color(c) 设置笔的颜色turtle.fillcolor(c) 设置笔填充颜色turtle.begin_fill() 在填充颜色前访问这个方法turtle ...