线程安全&Java内存模型
Java内存模型
Java内存模型(JMM)主要目标是定义多线程的情况下线程访问变量的规则。
JMM规定线程之间的共享变量存储在主内存中,每个线程都有一个本地内存(工作内存),本地内存存储了共享变量的副本。

关于线程安全
什么是线程安全问题?
当多个线程同时共享同一个全局变量做写的操作时候,可能会受到其他线程的干扰,导致数据脏读。(数据一致性问题)
如何解决线程安全问题?
核心思想:在同一时刻,只能有一个线程执行。
通过加锁使线程更加安全,也使程序的执行效率更低。
衡量线程安全的3个要素:
- 原子性:一个操作或者多个操作要么全部执行,要么都不执行
- 可见性:多个线程访问同一变量,一个线程修改了变量的值,其他线程可以立即看到修改的值
- 有序性:程序按照代码的顺序先后执行(与指令重排有关)
Volatile关键字
volatile是一种轻量级的同步机制,可以保证可见性【及时将修改的变量刷新到主内存中】,但不能保证原子性,并且禁止重排序。
volatile在多线程下的适用场景:一写多读
volatile如何保证内存可见性?
当一个线程对volatile修饰的变量进行写操作时,该线程中的本地内存的变量会被立刻刷新到主内存中。
当一个线程对volatile修饰的变量进行读操作时,该线程直接读取主内存的变量。
volatile能否保证线程安全?
不能,保证线程安全需要同时具备原子性,可见性和有序性。而volatile只能保证可见性和有序性,无法保证原子性。
Synchronized锁
核心思想:在多线程执行同一个方法时,只有获取到锁,才能进入方法里面执行
使用方式:
- 修饰一个类:其作用的范围是synchronized后面括号括起来的部分,作用的对象是这个类的所有对象;
- 修饰一个方法:被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
- 修饰一个静态的方法:其作用的范围是整个方法,作用的对象是这个类的所有对象;
- 修饰一个代码块:被修饰的代码块称为同步语句块,其作用范围是大括号{}括起来的代码块,作用的对象是调用这个代码块的对象;
重入锁
当一个线程已经获取到锁后,再次请求该锁,就可直接获取。(锁的传递性)
Synchronized属于可重入锁
Lock锁
自动挡Synchronized:Java关键字,在代码执行完或程序抛出异常自动释放锁
手动挡Lock:可以高度控制获取锁,释放锁的过程,扩展性极强
死锁
同步中嵌套同步,导致锁无法释放。
乐观锁与悲观锁
锁可以从不同的角度分类,乐观锁和悲观锁是其中一种。
乐观锁和悲观锁并不是锁的具体实现,而是并发控制的两种策略,或者说是抽象。
乐观锁(适合多读场景)
思想:认为不会发生线程冲突
执行流程,先读取数据,然后在更新前检查在读取至更新这段时间数据是否被修改
- 未修改:直接更新数据
- 已修改:重新读取,再次提交更新(或者放弃操作)
为什么乐观锁适合多读场景?
乐观锁是一种更新前的检查机制,相对于悲观锁来说在多读场景下可以减少锁的性能开销,对于多写场景,乐观锁会一直进入已修改,重新读取,再次提交的循环,反而带来更多的资源消耗。
悲观锁(适合多写场景)
思想:认为一定会发生线程冲突
执行流程:读取数据的时候上锁(其他用户无法读取),直到本次数据更新完成才会释放锁。在多写场景下,能保证较高的数据一致性。
【总的来说,乐观锁回滚重试,悲观锁阻塞事务】
线程安全&Java内存模型的更多相关文章
- Java 线程 — JMM Java内存模型
JMM Java Memory Model,Java内存模型,属于语言级的内存模型 并发编程中存在的问题: 如何通信:用于线程之间交换信息.两种方式:共享内存,消息传递 如何同步:用于控制不同线程间操 ...
- 【Java线程】Java内存模型总结
学习资料:http://www.infoq.com/cn/articles/Java-memory-model-1 Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态, ...
- (转)【Java线程】Java内存模型总结
Java的并发采用的是共享内存模型(而非消息传递模型),线程之间共享程序的公共状态,线程之间通过写-读内存中的公共状态来隐式进行通信.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变 ...
- 深入理解Java虚拟机(第三版)-13.Java内存模型与线程
13.Java内存模型与线程 1.Java内存模型 Java 内存模型的主要目的是定义程序中各种变量的访问规则,即关注在虚拟机中把变量值存储到主内存和从内存中取出变量值的底层细节 该变量指的是 实例字 ...
- java内存模型和线程
概述 多任务的处理在现在的计算机中可以说是"标配"了,在许多的情况下,让计算机同时做几件事情,不仅是因为计算机的运算能力的强大,还有一个重要的原因是:cpu的运算速度和计算机的存储 ...
- java内存模型与线程(转) good
java内存模型与线程 参考 http://baike.baidu.com/view/8657411.htm http://developer.51cto.com/art/201309/410971_ ...
- JAVA内存模型与线程
概述 由于计算机的运算速度和它的存储和通讯子系统的速度差距巨大,大部分时间都花在IO,网络和数据库上.为了压榨CPU的运算能力,需要并发.另外,优秀的并发程序对于提高服务器的TPS有重要的意义. 硬件 ...
- Java内存模型与Java线程实现原理
硬件的效率与一致性 基于高速缓存的存储交互很好的解决了处理器和内存的速度矛盾,但是也为计算机系统带来了更高的复杂度,因为引入了一个新问题:缓存一致性. 在多处理器系统中,每个处理器都有自己的高速缓存, ...
- 深入理解JVM(6)——Java内存模型和线程
Java虚拟机规范中定义了Java内存模型(Java Memory Model,JMM)用来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果(“即Ja ...
随机推荐
- SonarQube+Jenkins+Cppcheck实现C++代码扫描
背景:公司部分项目是由C++进行开发,因此对此有需求. sonarqube:docker化安装(alpine系统),版本8.3.1 (build 34397) jenkins:docker化安装,版本 ...
- jdk安装无反应解决方法
找到该文件(隐藏文件),如果里面是只有空格,清空后重新安装就可以.若有内容设置INSTALL_SILENT=0 后重新安装.
- OSCP Learning Notes - Exploit(3)
Modifying Shellcode 1. Search “vulnserver exploit code” on the Internet. Find the following website ...
- Oracle DataGuard主库丢失归档日志后备库的RMAN增量恢复一例
第一部分 问题描述和环境状态确认 ----1. 问题场景 Oracle DataGuard主库丢失archivelog,如何不重建备库完成同步? 在Oracle DataGuard主从同步过程中可能 ...
- 我和ABP vNext 的故事
Abp VNext是Abp的.NET Core 版本,但它不仅仅只是代码重写了.Abp团队在过去多年社区和商业版本的反馈上做了很多的改进.包括性能.底层的框架设计,它融合了更多优雅的设计实践.不管你是 ...
- less : 写一个display:flex的mixin
和scss一样,less也是一个好用的css预处理语言,语法也很相近. 而我们在使用display:flex的时候,很容易苦恼于里面的设置的单词很难记(尤其是对我这种英语很差的人来说). 所以我们可以 ...
- 如果你还不知道如何控制springboot中bean的加载顺序,那你一定要看此篇
1.为什么需要控制加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了spi机制,用spring.factories可以完成一个小组件的自动装配功 ...
- LeetCode 85 | 如何从矩阵当中找到数字围成的最大矩形的面积?
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题53篇文章,我们一起来看看LeetCode中的85题,Maximal Rectangle(最大面积矩形). 今天的 ...
- jmeter正则表达式,萌新入门篇
@@@@@@@@@@@@ 透过现象看本质 jmeter中正则表达式对我们来说,就是一个工具,他可以帮助我们做的事就是从一堆数据中截取出我们想要的字段,比如从setcookie:DERF12456DAS ...
- linux 命令行 拯救萌新精简版
装上linux 真机而不会命令行简直是太难了(这是什么人间疾苦) 于是,来几个非常基础的命令行,给(像我这样)的萌新们一点点前进的动力,也给奋斗在linux路上的大佬们一点点来自萌新的敬意吧. 一个非 ...