线程安全&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 ...
随机推荐
- 数据可视化实例(十): 相关图(matplotlib,pandas)
相关图 https://datawhalechina.github.io/pms50/#/chapter8/chapter8 导入所需要的库 import numpy as np # 导入numpy库 ...
- hihoCoder 1052 基因工程 最详细的解题报告
题目来源:基因工程 解题思路:假设基因序列长度为N,则需要计算基因序列前K个和后K个相同所需要的最少改变次数sum. 假设基因序列为 ATACGTCT (即M=8),K=6:interval=M-K= ...
- 深入浅出ReentrantLock源码解析
ReentrantLock不但是可重入锁,而且还是公平或非公平锁,在工作中会经常使用到,将自己对这两种锁的理解记录下来,希望对大家有帮助. 前提条件 在理解ReentrantLock时需要具备一些基本 ...
- [斯坦福大学2014机器学习教程笔记]第六章-决策界限(decision boundary)
这一节主要介绍的是决策界限(decision boundary)的概念,这个概念可以帮组我们更好地理解逻辑回归的假设函数在计算什么. 首先回忆一下上次写的公式. 现在让我们进一步了解这个假设函数在什么 ...
- 一文快速掌握华为云IPv6基础知识及使用指南
随着5G.物联网等新兴技术领域的发展,IP空间需求巨大,IPv6成为万物互联的基础,势在必行:华为云作为IPv6成熟商用开拓者,针对金融.广电.媒资等不同行业推出IPv6解决方案,助力企业平滑升级到I ...
- Python实现性能自动化测试的方法【推荐好文】
1.什么是性能自动化测试? ◆ 性能 △ 系统负载能力 △ 超负荷运行下的稳定性 △ 系统瓶颈 ◆ 自动化测试 △ 使用程序代替手工 △ 提升测试效率 ◆ 性能自动化 △ 使用代码模拟大批量用户 △ ...
- 图解:如何实现最小生成树(Prim算法与Kruskal算法)
这是图算法的第四篇文章 图解:如何实现最小生成树 文章目录: 1.概念和性质 2.思路探索 3.Kruskal算法 4.Prim算法 5.代码实现 1.概念和性质 今天我们考虑的模型是加权无向图,问题 ...
- LGTB 与 序列
题目描述 LGTB 有一个长度为 N 的序列 A ,现在他想构造一个新的长度为 N 的序列 B ,使得 B 中的任意两个数都互质.并且他要使 \sum_{1\le i\le N}|A_i-B_i| 最 ...
- Mnist手写数字识别 Tensorflow
Mnist手写数字识别 Tensorflow 任务目标 了解mnist数据集 搭建和测试模型 编辑环境 操作系统:Win10 python版本:3.6 集成开发环境:pycharm tensorflo ...
- vue+axios+springboot文件下载
//前台代码 <el-button size="medium" type="primary" @click="downloadFile" ...