线程安全&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 ...
随机推荐
- 09-Python异常
一.简介 在实际的工作过程中,我们会遇到各种问题,比如文件不存在,代码运行不符合某些特定逻辑等,程序在运行时,遇到这些问题便会发生异常.英文是Exception. a = float(input('请 ...
- md5加密密码
using System.Security.Cryptography; public string GetStrMd5(string ConvertString) { MD5CryptoService ...
- Crystal Reports --报表设计
完整的报表解决方案 数据访问—>报表设计—>报表管理—>与应用系统集成 一.规划报表 设计报表的准备工作 谁看报表? 报表的数据是什么?(页眉页脚的内容?是否需要分组?是否需要汇总? ...
- 哈夫曼编码+python实现
关于哈夫曼树怎么构建的.哈夫曼编码怎么求,请参考 哈夫曼树及python实现 这些基础的东西就不在这里阐述了,本文直接上代码. 参考链接:哈夫曼树的 Python 实现 哈夫曼树的构建和编码 ''' ...
- CodeForces - 722C Destroying Array (并查集/集合的插入和删除)
原题链接:https://vjudge.net/problem/511814/origin Description: You are given an array consisting of n no ...
- Vue.js +pdf.js 处理响应pdf文件流数据,前端转图片预览不可下载
使用场景及原因 实际业务中,一些说明书或协议仅支持用户在线预览,为避免用户自行下载,并进行修改,引发纠纷,特将文件已文件流的形式,传给前端并转为图片显示,此时可能会有人问,为什么不直接在后端转图片,前 ...
- java 如何正确的输出集合或者对象的值
java 如何正确的输出集合或者对象的值 一般out.println(Object) 和 System.out.println(Object),其中输出的都是Object.toString()方法.重 ...
- 面试题五十四:二叉搜索树的第K大节点
方法:搜索二叉树的特点就是左树小于节点,节点小于右树,所以采用中序遍历法就可以得到排序序列 BinaryTreeNode KthNode(BinaryTreeNode pNode ,int k){ i ...
- C语言中对文件的读写的一些浅显理解
前述:基于上学期完成的数据结构的课程设计,对于老师的提出要求实现的基础上,自己在使用过程中发现每次打开程序都需要重新输入数据,于是便决定,将文件读写功能加入此次课程设计中,以下是我的一些心得和浅显理解 ...
- Error: no such table: device;的问题的解决,去掉表名device后面的分号;
sqlite> .mode csvsqlite> .import device.txt device;Error: no such table: device;sqlite> .im ...