1、计算机

首先我们需要讲解下计算机的模型:现代计算机模型是基于-冯诺依曼计算机模型

我们不用管输入和输出设备,最主要的就是中间计算器和存储器之间的交互,也就是CPU与主内存之间取数、存数。

大家会看到有一个IO总线在进行数据的流通,所以CPU与此磁盘的交互也会通过IO总线,但是IO总线上有其他的一些数据在流通,比如显示器、鼠标键盘等,并且现在的CPU计算速度普遍在GHz,但是我们的内存输出的却是MB,这大大影响了CPU,因为每次取数都要经过IO中线,难免会影响IO,所以CPU有了三级缓存,L1、L2、L3,缓存存储些指令集什么的。如下图:

CPU读取存储器数据过程

CPU要取寄存器XX的值,只需要一步:直接读取。

CPU要取L1 cache的某个值,需要1-3步(或者更多):把cache行锁住,把某个数据拿来,解锁,如果没锁住就慢了。

CPU要取L2 cache的某个值,先要到L1 cache里取,L1当中不存在,在L2里,L2开始加锁,加锁以后,把L2里的数据复制到L1,再执行读L1的过程,上面的3步,再解锁。

CPU取L3 cache的也是一样,只不过先由L3复制到L2,从L2复制到L1,从L1到CPU。

CPU取内存则最复杂:通知内存控制器占用总线带宽,通知内存加锁,发起内存读请求,等待回应,回应数据保存到L3(如果没有就到L2),再从L3/2到L1,再从L1到CPU之后解除总线锁定。

缓存一致性问题:当有多个处理器的时候,如何保证CPU1与CPU2之间的数据是一致的,为了保证数据性一致,需要在访问缓存的同时,遵循一些协议如MESI,最后以谁的缓存为最后结果。

2、什么是线程

现代操作系统在运行一个程序时,会为其创建一个进程。例如,启动一个Java程序,操作系统就会创建一个Java进程。现代操作系统调度CPU的最小单元是线程,也叫轻量级进程(Light Weight Process),在一个进程里可以创建多个线程,这些线程都拥有各自的计数器、堆栈和局部变量等属性,并且能够访问共享的内存变量。处理器在这些线程上高速切换,让使用者感觉到这些线程在同时执行。线程的实现可以分为两类:

1、用户级线程(User-Level Thread)

2、内核线线程(Kernel-Level Thread)

用户线程:指不需要内核支持而在用户程序中实现的线程,其不依赖于操作系统核心,应用进程利用线程库提供创建、同步、调度和管理线程的函数来控制用户线程。另外,用户线程是由应用进程利用线程库创建和管理,不依赖于操作系统核心。不需要用户态/核心态切换,速度快。操作系统内核不知道多线程的存在,因此一个线程阻塞将使得整个进程(包括它的所有线程)阻塞。由于这里的处理器时间片分配是以进程为基本单位,所以每个线程执行的时间相对减少。

内核线程:线程的所有管理操作都是由操作系统内核完成的。内核保存线程的状态和上下文信息,当一个线程执行了引起阻塞的系统调用时,内核可以调度该进程的其他线程执行。在多处理器系统上,内核可以分派属于同一进程的多个线程在多个处理器上运行,提高进程执行的并行度。由于需要内核完成线程的创建、调度和管理,所以和用户级线程相比这些操作要慢得多,但是仍然比进程的创建和管理操作要快。大多数市场上的操作系统,如Windows,Linux等都支持内核级线程。

我们每创建一个线程,jvm都会帮我们在内核空间创建一个线程,这样就避免了jvm来管理线程使操作系统不知道线程的存在,只知道jvm这一个进程,所以一旦jvm中的线程堵塞,CPU是不会进行上下文切换的,导致整个jvm进程都会堵塞。

三、为什么用到并发?并发会产生什么问题?

并发编程的本质其实就是利用多线程技术,在现代多核的CPU的背景下,催生了并发编程的趋势,通过并发编程的形式可以将多核CPU的计算能力发挥到极致,性能得到提升。除此之外,面对复杂业务模型,并行程序会比串行程序更适应业务需求,而并发编程更能吻合这种业务拆分 。

即使是单核处理器也支持多线程执行代码,CPU通过给每个线程分配CPU时间片来实现这个机制。时间片是CPU分配给各个线程的时间,因为时间片非常短,所以CPU通过不停地切换线程执行,让我们感觉多个线程是同时执行的,时间片一般是几十毫秒(ms)。

并发不等于并行:并发指的是多个任务交替进行,而并行则是指真正意义上的“同时进行”。实际上,如果系统内只有一个CPU,而使用多线程时,那么真实系统环境下不能并行,只能通过切换时间片的方式交替进行,而成为并发执行任务。真正的并行也只能出现在拥有多个CPU的系统中。

并发的优点:

1充分利用多核CPU的计算能力;

2方便进行业务拆分,提升应用性能;

并发产生的问题:

1.高并发场景下,导致频繁的上下文切换

2.临界区线程安全问题,容易出现死锁的,产生死锁就会造成系统功能不可用

CPU通过分配时间片来每次循环任务,每次需要切换到下一个任务时,都会保存上一个任务的结束状态,以便切换回来可以在加载这个任务,所以任务从保存到再加载的过程就是一次上下文切换。

四、什么是JMM模型?

JMM并不真实存在,只是一种规范,通过这种规范来让定义程序中各个变量的访问方式。JVM运行程序的实体是线程,而每个线程创建时JVM都会为其创建一个工作内存(有些地方称为栈空间),用于存储线程私有的数据,而Java内存模型中规定所有变量都存储在主内存,主内存是共享内存区域,所有线程都可以访问,但线程对变量的操作(读取赋值等)必须在工作内存中进行,首先要将变量从主内存拷贝的自己的工作内存空间,然后对变量进行操作,操作完成后再将变量写回主内存,不能直接操作主内存中的变量,工作内存中存储着主内存中的变量副本拷贝,前面说过,工作内存是每个线程的私有数据区域,因此不同的线程间无法访问对方的工作内存,线程间的通信(传值)必须通过主内存来完成

JMM是围绕原子性,有序性、可见性展开

JMM-同步八种操作介绍

(1)lock(锁定):作用于主内存的变量,把一个变量标记为一条线程独占状态

(2)unlock(解锁):作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定

(3)read(读取):作用于主内存的变量,把一个变量值从主内存传输到线程的工作内存中,以便随后的load动作使用

(4)load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中

(5)use(使用):作用于工作内存的变量,把工作内存中的一个变量值传递给执行引擎

(6)assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量

(7)store(存储):作用于工作内存的变量,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作

(8)write(写入):作用于工作内存的变量,它把store操作从工作内存中的一个变量的值传送到主内存的变量中

如果要把一个变量从主内存中复制到工作内存中,就需要按顺序地执行read和load操作,如果把变量从工作内存中同步到主内存中,就需要按顺序地执行store和write操作。但Java内存模型只要求上述操作必须按顺序执行,而没有保证必须是连续执行。

ps:关注一下本人博客,每周都有更新内容哦!

java内存模型作用是什么意思_JMM(Java内存模型)是什么?为什么使用并发?相关推荐

  1. 计算机硬件中内存的作用是什么,系统硬件中内存XMP是什么意思?有必要开吗?内存XMP模式的作用与开启教程...

    系统硬件中内存是电脑与CPU进行沟通的桥梁,它是一台电脑不可或缺的硬件之一,重要性至关重要.而我们在选购内存的时候,会看到在一些内存参数中注明支持X.M.P,那么电脑内存XMP是什么意思?有必要开吗? ...

  2. java继承的作用_Java继承概述以及Java继承案例和继承的好处

    Java继承概述 1.多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些相同属性和行为,只要继承那个类即可. 2.在Java中通过extends关键字可以实现类与类的 ...

  3. keyboard类在Java中的作用_keyboard – 死键在Java Swing应用程序中不起作用

    我目前正在使用Ubuntu 10.10和Netbeans 7.0,我不能再用死键键入重音字母了.它不是特定于版本的问题似乎与Swing有关,因为我对旧版本的Netbeans和操作系统有同样的问题. 当 ...

  4. java parallel.for作用_“Parallel.For”for Java?

    我想最接近的事情是: ExecutorService exec = Executors.newFixedThreadPool(SOME_NUM_OF_THREADS); try { for (fina ...

  5. java内存模型作用是什么_什么是JVM内存模型?

    本篇文章带大家初步了解一下JVM内存模型,有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 计算机内存模型 在程序运行时,CPU通过访问主存获取数据,但随着CPU的快速发展,CPU访问 ...

  6. 【Android 内存优化】Java 内存模型 ( Java 虚拟机内存模型 | 线程私有区 | 共享数据区 | 内存回收算法 | 引用计数 | 可达性分析 )

    文章目录 一. Java 虚拟机内存模型 二. 程序计数器 ( 线程私有区 ) 三. 虚拟机栈 ( 线程私有区 ) 四. 本地方法栈 ( 线程私有区 ) 五. 方法区 ( 共享数据区 ) 1. 方法区 ...

  7. 内存位置访问无效_万字长文——java内存模型之volatile深入解读

    在阅读本文前,请思考以下的面试题? volatile是什么? volatile的特性 volatile是如何保证可见性的? volatile是如何保证有序性的? volatile可以保证原子性吗? 使 ...

  8. java零碎要点001--深入理解JVM_Java的堆内存_栈内存_以及运行时数据区的作用

    程序计数器:可以看做当前线程运行所执行的字节码的行号指示器,在虚拟机的概念模型中,字节码解释器工作时就是 通过改变这个计数器的值来选取下一条需要执行的字节码指令.由于JVM多线程是通过线程轮流切换并分 ...

  9. java很贵可以用before代替吗_Java内存模型与Volatile,Happen-Before原则等

    Java的内存模型 Java内存模型(JMM)是一个抽象的模型.决定了线程主要定义了线程和内存间的抽象关系:主内存存放的是线程共享变量,每个线程有自己的工作内存,存放变量的副本,只能对副本进行读写,副 ...

最新文章

  1. 985 博士:导师是院士,直到毕业,我们都没单独说过一句话...
  2. python安装第三方库-python第三方库的四种安装方法
  3. 原创全新打包工具Parcel零配置VueJS开发脚手架
  4. Android OTA 升级之三:生成recovery.img
  5. 03 php,PHP 03 选择结构
  6. NET Core 指令启动
  7. com.alibaba.dubbo.rpc.RpcException: Forbid consumer 192.168.184.1 access service com.foreveross.syst
  8. Python中的super()简单用法
  9. 作为研究生/博士生导师招收的第一个学生是一种怎样的体验?
  10. matlab 逆矩阵计算器,高等数学计算器
  11. 计算机省vb二级试题,江苏省计算机二级VB试题及答案
  12. 电动机正反转继电器控制系统
  13. 前端,后端,前台,后台到底应该怎么理解。
  14. 数据的逻辑结构包括那些?
  15. Learn Git Branching 答案
  16. drm单个framebuffer显示
  17. R语言使用caret包的confusionMatrix函数计算混淆矩阵、基于混淆矩阵的信息手动编写函数计算accuray、准确率指标
  18. rust php 扩展,在PHP程序中使用Rust扩展的方法
  19. 锡瓦塔内霍 墨西哥 / 巴克斯顿 /
  20. Qt网络编程概述(一)

热门文章

  1. 为什么谷歌浏览器修改主题背景,只有标签栏变了,但新标签页背景不变?怎么办?
  2. 用 C语言模拟买猫的过程
  3. 转:NO.523 Aidan HawkenCarina Round - Walking Blind
  4. 前端面试总结——http、html和浏览器篇
  5. c语言电话本程序代码,C语言程序设计之电话簿
  6. MAXENT模型的生物多样性生境模拟
  7. HTML视频学习教程,让你实战入门前端
  8. hexo图片展示-blog图床迁移至七牛云
  9. 粒子群算法的matlab实现(一)
  10. python将中文汉字转换成拼音