并发编程 原子性 可见性 有序性

news/2024/11/28 1:38:01/

在这里插入图片描述

并发编程的三个重要特性

原子性所谓原子性是指在一次的操作或者多次操作中,要么所有的操作全部都得到了执行并且不会受到任何因素的干扰而中断,要么所有的操作都不执行。
可见性可见性是指,当一个线程对共享变量进行了修改,那么另外的线程可以立即看到修改后的最新值。
有序性所谓有序性是指程序代码在执行过程中的先后顺序,由于Java在编译器以及运行期的优化,导致了代码的执行顺序未必就是开发者编写代码时的顺序。

JMM如何保证三大特性

JMM与原子性

原子性操作非原子
对基本数据类型的变量读取赋值操作都是原子性的多个原子性的操作在一起就不再是原子性操作
对引用类型的变量读取和赋值的操作也是原子性的y++
get iy=x
i+1z=z+1
set ix=10
Java如何保证原子性性
JMM只保证了基本读取和赋值的原子性操作,其他的均不保证
使用关键字synchronized
使用JUC中的lock
如果想要使得int等类型自增操作具备原子性,可以使用JUC包下的原子封装类型java.util.concurrent.atomic.*

JMM与可见性

在多线程的环境下,如果某个线程首次读取共享变量,则首先到主内存中获取该变量,然后存入工作内存中,以后只需要在工作内存中读取该变量即可。
同样如果对该变量执行了修改的操作,则先将新值写入工作内存中,然后再刷新至主内存中。但是什么时候最新的值会被刷新至主内存中是不太确定的。
Java提供了以下三种方式来保证可见性
使用关键字volatile当一个变量被volatile关键字修饰时,对于共享资源的读操作会直接在主内存中进行(当然也会缓存到工作内存中,当其他线程对该共享资源进行了修改,则会导致当前线程在工作内存中的共享资源失效,所以必须从主内存中再次获取),对于共享资源的写操作当然是先要修改工作内存,但是修改结束后会立刻将其刷新到主内存中
1)Reader线程从主内存中获取init_value的值为0,并且将其缓存到本地工作内存中。
2)Updater线程将init_value的值在本地工作内存中修改为1,然后立即刷新至主内存中。
3)Reader线程在本地工作内存中的init_value失效(反映到硬件上就是CPU的L1或者L2的Cache Line失效)。
4)由于Reader线程工作内存中的init_value失效,因此需要到主内存中重新读取init_value的值。
通过synchronized关键字能够保证可见性synchronized关键字能够保证同一时刻只有一个线程获得锁,然后执行同步方法,并且还会确保在锁释放之前,会将对变量的修改刷新到主内存当中。
通过JUC提供的显式锁Lock也能够保证可见性Lock的lock方法能够保证在同一时刻只有一个线程获得锁然后执行同步方法,并且会确保在锁释放(Lock的unlock方法)之前会将对变量的修改刷新到主内存当中。

JMM与有序性

在Java的内存模型中,允许编译器和处理器对指令进行重排序,在单线程的情况下,重排序并不会引起什么问题
但是在多线程的情况下,重排序会影响到程序的正确运行
Java提供了三种保证有序性的方式
使用volatile关键字来保证有序性volatile关键字对顺序性的保证就比较霸道一点,直接禁止JVM和处理器对volatile关键字修饰的指令重排序,但是对于volatile前后无依赖关系的指令则可以随便怎么排序
使用synchronized关键字来保证有序性同步代码在执行的时候与在单线程情况下一样自然能够保证顺序性(最终结果的顺序性
使用显式锁Lock来保证有序性同步代码在执行的时候与在单线程情况下一样自然能够保证顺序性(最终结果的顺序性

-----------------------------------------------------------------------------读书笔记摘自书名:Java高并发编程详解:多线程与架构设计 作者:汪文君


http://www.ppmy.cn/news/105232.html

相关文章

Spring Boot注解的使用细节

RequestParam: 1、在前端传入多个相同的属性时,若使用数组接收,则无需使用RequestParam注解。若使用集合接收,则须使用RequestParam来绑定参数。 2、当前端发送的属性名与服务端接收的不一致时,可以使用RequestParam&a…

java-反射

反射 示例代码 import java.lang.reflect.*; public class Example {public static void main(String[] args) throws Exception {// 获取 Class 对象Class<?> clazz Class.forName("java.lang.String");// 获取类名、包名和修饰符String className clazz…

产品经理-产品驱动增长3-共识体验

公式&#xff1a;增长需求方案共识体验场域效率口碑流量&#xff0c;篇幅问题&#xff0c;这篇我们讲两个&#xff0c;分别是共识和体验 一、共识 前面我们研究了需求和方案&#xff0c;用介绍的方法已经为G公司和K公司的产品分别梳理了一条核心需求&#xff0c;并且还有三个方…

华为OD机试真题B卷 Java 实现【停车场车辆统计】,附详细解题思路

一、题目描述 特定大小的停车场&#xff0c;数组cars[]表示&#xff0c;其中1表示有车&#xff0c;0表示没车。 车辆大小不一&#xff0c;小车占一个车位&#xff08;长度1&#xff09;&#xff0c;货车占两个车位&#xff08;长度2&#xff09;&#xff0c;卡车占三个车位&a…

操作系统期末复习——课时十内存管理(一)

1、内存管理的基本原理和要求 1&#xff09;内存管理的定义 操作系统对内存的划分和动态分配就是内存管理的概念。 2&#xff09;内存管理的功能 &#xff08;1&#xff09;内存空间的分配和回收&#xff1a;由操作系统完成对主存的分配和回收&#xff0c;对编程人员透明。 &…

最热门高效的Node.JS开源第三方开发库和特点(持续更新......)

目录 1. Express 2. Socket.io 3. Mongoose 4. Passport 5. Async 6. PM2 7. Nodemailer 8. Request 9. Cheerio 10. Lodash 11. Bluebird 12. Winston 13. Socket.io-client 14. Node-sass 15. Moment 16. Gulp 17. Grunt 18. Chai 19. Sinon 20. Nodemon…

「SQL面试题库」 No_82 报告系统状态的连续日期

&#x1f345; 1、专栏介绍 「SQL面试题库」是由 不是西红柿 发起&#xff0c;全员免费参与的SQL学习活动。我每天发布1道SQL面试真题&#xff0c;从简单到困难&#xff0c;涵盖所有SQL知识点&#xff0c;我敢保证只要做完这100道题&#xff0c;不仅能轻松搞定面试&#xff0…

电子科技大学编译原理复习笔记(六):自上而下的语法分析

目录 前言 重点一览 引言 语法分析的功能 语法分析的分类 自上而下分析方法 回溯分析法 回溯分析法例子 方法 存在的问题 产生的原因 特点 解决缺陷 消除回溯&#xff08;重点&#xff09; 递归下降分析器 递归下降分析法 递归过程的构造 扩充BNF 改进的递…