原子性

​原子性指的是一个或者多个操作在 CPU 执行的过程中不被中断的特性

在多线程情况下,线程会被操作系统调度进行任务切换,占有CPU时间片段的就执行,否则就阻塞

java中对基础类型的变量赋值是原子性的,int  a = 1 ;

但是像这种语句 count++; 在执行的时候,包含3的指令操作

指令 1:首先,需要把变量 count 从内存加载到 CPU的寄存器

指令 2:在寄存器中执行 +1 操作

指令 3:最后,将结果写入内存

在一个线程里执行是没有问题的,但是在多线程情况下,会引发数据不一致问题

对于上面的三条指令来说,如果线程 A 在指令 1 执行完后做线程切换,线程 A 和线程 B 按照下图的序列执行,那么我们会发现两个线程都执行了 count+=1 的操作,但是得到的结果不是我们期望的 2,而是 1。

可见性

可见性指的是当一个线程修改了共享变量后,其他线程能够立即得知这个修改,volatile可以保证可见性

有序性

​ 有序性指的是程序按照代码的先后顺序执行

为了性能优化,编译器和处理器会可能进行指令重排序,有时候会改变程序中语句的先后顺序

a = 5;     //1
b = 20; //2
c = a + b; //3
编译器优化后可能变成
b = 20;    //1
a = 5; //2
c = a + b; //3
编译器调整了语句的顺序,在单线程中并没有什么影响,但是在多线程中可能会出现异常
单例模式有一种实现是
public class Singleton {
static Singleton instance;
static Singleton getInstance(){
if (instance == null) {
synchronized(Singleton.class) {
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}

我们先看 instance = new Singleton() 的未被编译器优化的操作

  • 指令 1:分配一块内存 M;
  • 指令 2:在内存 M 上初始化 Singleton 对象;
  • 指令 3:然后 M 的地址赋值给 instance 变量。

编译器优化后的操作指令

  • 指令 1:分配一块内存 M;
  • 指令 2:将 M 的地址赋值给 instance 变量;
  • 指令 3:然后在内存 M 上初始化 Singleton 对象。
现在有A,B两个线程,我们假设线程A先执行getInstance()方法,当执行编译器优化后的操作指令2时(此时候未完成对象的初始化),这时候发生了线程切换,那么线程B进入,刚好执行到第一次判断instance == null 会发现instance
不等于null了,所以直接返回instance,而此时instance是没有初始化的

Java并发之原子性,可见性,有序性的更多相关文章

  1. Java高并发--原子性可见性有序性

    Java高并发--原子性可见性有序性 主要是学习慕课网实战视频<Java并发编程入门与高并发面试>的笔记 原子性:指一个操作不可中断,一个线程一旦开始,直到执行完成都不会被其他线程干扰.换 ...

  2. Java内存模型JMM 高并发原子性可见性有序性简介 多线程中篇(十)

    JVM运行时内存结构回顾 在JVM相关的介绍中,有说到JAVA运行时的内存结构,简单回顾下 整体结构如下图所示,大致分为五大块 而对于方法区中的数据,是属于所有线程共享的数据结构 而对于虚拟机栈中数据 ...

  3. jvm高级特性(5)(1)(原子性,可见性,有序性,volatile,概述)

    JVM高级特性与实践(十二):高效并发时的内外存交互.三大特征(原子.可见.有序性) 与 volatile型变量特殊规则 简介: 阿姆达尔定律(Amdahl):该定律通过系统中并行化与串行化的比重来描 ...

  4. Java核心复习—— 原子性、有序性与Happens-Before

    一. 产生并发Bug的源头 可见性 缓存导致的可见性问题 原子性 线程切换带来的原子性问题 有序性 编译优化带来的有序性问题 上面讲到了 volatile 与可见性,本章再主要讲下原子性.有序性与Ha ...

  5. java并发之原子性、可见性、有序性

    链接:https://blog.csdn.net/gongpulin/article/details/51211616

  6. java 原子性 可见性 有序性

    原子性 原子性是指一个操作或多个操作要么全部执行完成且执行过程不被中断,要么就不执行. 如向变量x赋值操作 x = 10 是原子性的,就不会出现赋值操作进行到一半(x的低16位赋值成功,高16位没有赋 ...

  7. Java 并发之原子性与可见性

    原子性 原子是世界上的最小单位,具有不可分割性.比如 a=0:(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作.再比如:a++: 这个操作实际是a = a + 1 ...

  8. java并发之原子性

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp17 1.原子性操作: 不能被线程调度机制中断的操作:--对原子性变量的赋值 ...

  9. Java自增原子性问题(测试Volatile、AtomicInteger)

    这是美团一面面试官的一个问题,后来发现这是一道面试常见题,怪自己没有准备充分:i++;在多线程环境下是否存在问题?当时回答存在,接着问,那怎么解决?...好吧,我说加锁或者synchronized同步 ...

随机推荐

  1. MyBatis面试题集合,90%会遇到这些问题

    1.#{}和${}的区别是什么? ${}是Properties文件中的变量占位符,它可以用于标签属性值和sql内部,属于静态文本替换,比如${driver}会被静态替换为com.mysql.jdbc. ...

  2. SQLServer 高效 分页存储过程

    /********************************************************************** 参数:@PrimaryKey 主键,@OrderBy 排 ...

  3. CoreData数据库搭建

    1.首先创建父类吧重用的代码写在里边 #import <Foundation/Foundation.h> #import <CoreData/CoreData.h> @inte ...

  4. Android输出日志Log类并保存到文件中

    android.util.Log常用的方法有以下5个: Log.v() Log.d() Log.i() Log.w() 以及 Log.e().根据首字母分别对应VERBOSE,DEBUG,INFO,W ...

  5. vue学习指南:第三篇(详细) - vue的生命周期

    今天小编给大家详细讲解一下 vue 的生命周期.希望大家多多指教,哪里有遗漏的地方,也请大家指点出来 谢谢. 一. 怎么理解 Vue 的生命周期的? 生命周期:从无到有,到到无的一个过程.Vue的生命 ...

  6. Object_C 集成环信时,中文环境下不显示中文

    因为本app只有中文,没有做中英文判断,但是环信是默认英文环境的,所以,此时,需要在info.plist 文件中修改它的语言环境.如下

  7. 5.InfluxDB-InfluxQL基础语法教程--WHERE子句

    本文翻译自官网,官网地址:(https://docs.influxdata.com/influxdb/v1.7/query_language/data_exploration/) WHERE子句 语法 ...

  8. Python 简易的异步协程使用方法

    代码 import asyncio async def ex(id, n): print(id+" start") await asyncio.sleep(n/2) print(i ...

  9. Jenkins参数化构建(七)

    一.配置参数化构建过程 主要用来区分分支,使用传参的方式,将分支名称传入脚本中进行拉取代码. 1.1 最常用的是:字符参数.文本参数.  1.2 添加字符参数和文本参数,并配置变量名称  1.3 配置 ...

  10. paxos算法—今生

    Paxos 定义2.1  票:即弱化形式的锁.它具备下面几个性质: 可重新发布:服务器可以重新发布新票,即使前面发布的票没有释放. 票可以过期:客户端用一张票来给服务器发送命令请求时,只有当这张票是最 ...