首页 > 编程语言 >Java面试之多线程&并发篇(9)

Java面试之多线程&并发篇(9)

时间:2024-11-29 18:21:47浏览次数:11  
标签:Java 并发 线程 内存 JMM 多线程 CPU

前言

本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!引用类型有哪些?有什么区别?说说你对JMM内存模型的理解?为什么需要JMM?多线程有什么用?似乎有点模糊了,那就大概看一下面试题吧。好记性不如烂键盘

*** 12万字的java面试题整理 ***
*** java核心面试知识整理 ***
*** Java高频面试讲解视频(知识涵盖齐全) ***

说说你对JMM内存模型的理解?为什么需要JMM?

随着CPU和内存的发展速度差异的问题,导致CPU的速度远快于内存,所以现在的CPU加入了高速缓存,高速缓存一般可以分为L1、L2、L3三级缓存。基于上面的例子我们知道了这导致了缓存一致性的问题,所以加入了缓存一致性协议,同时导致了内存可见性的问题,而编译器和CPU的重排序导致了原子性和有序性的问题,JMM内存模型正是对多线程操作下的一系列规范约束,因为不可能让陈雇员的代码去兼容所有的CPU,通过JMM我们才屏蔽了不同硬件和操作系统内存的访问差异,这样保证了Java程序在不同的平台下达到一致的内存访问效果,同时也是保证在高效并发的时候程序能够正确执行。

  • 原子性:Java内存模型通过read、load、assign、use、store、write来保证原子性操作,此外还有lock和unlock,直接对应着synchronized关键字的monitorenter和monitorexit字节码指令。
  • 可见性:可见性的问题在上面的回答已经说过,Java保证可见性可以认为通过volatile、synchronized、final来实现。
  • 有序性:由于处理器和编译器的重排序导致的有序性问题,Java通过volatile、synchronized来保证。

happen-before规则

虽然指令重排提高了并发的性能,但是Java虚拟机会对指令重排做出一些规则限制,并不能让所有的指令都随意的改变执行位置,主要有以下几点:

  1. 单线程每个操作,happen-before于该线程中任意后续操作
  2. volatile写happen-before与后续对这个变量的读
  3. synchronized解锁happen-before后续对这个锁的加锁
  4. final变量的写happen-before于final域对象的读,happen-before后续对final变量的读
  5. 传递性规则,A先于B,B先于C,那么A一定先于C发生

说了半天,到底工作内存和主内存是什么?

主内存可以认为就是物理内存,Java内存模型中实际就是虚拟机内存的一部分。而工作内存就是CPU缓存,他有可能是寄存器也有可能是L1\L2\L3缓存,都是有可能的。

多线程有什么用?

一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡。所谓"知其然知其所以然","会用"只是"知其然","为什么用"才是"知其所以然",只有达到"知其然知其所以然"的程度才可以说是把一个知识点运用自如。OK,下面说说我对这个问题的看法:
(1)发挥多核CPU的优势
随着工业的进步,现在的笔记本、台式机乃至商用的应用服务器至少也都是双核的,4核、8核甚至16核的也都不少见,如果是单线程的程序,那么在双核CPU上就浪费了50%,在4核CPU上就浪费了75%。单核CPU上所谓的"多线程"那是假的多线程,同一时间处理器只会处理一段逻辑,只不过线程之间切换得比较快,看着像多个线程"同时"运行罢了。多核CPU上的多线程才是真正的多线程,它能让你的多段逻辑同时工作,多线程,可以真正发挥出多核CPU的优势来,达到充分利用CPU的目的。
(2)防止阻塞
从程序运行效率的角度来看,单核CPU不但不会发挥出多线程的优势,反而会因为在单核CPU上运行多线程导致线程上下文的切换,而降低程序整体的效率。但是单核CPU我们还是要应用多线程,就是为了防止阻塞。试想,如果单核CPU使用单线程,那么只要这个线程阻塞了,比方说远程读取某个数据吧,对端迟迟未返回又没有设置超时时间,那么你的整个程序在数据返回回来之前就停止运行了。多线程可以防止这个问题,多条线程同时运行,哪怕一条线程的代码执行读取数据阻塞,也不会影响其它任务的执行。
(3)便于建模
这是另外一个没有这么明显的优点了。假设有一个大的任务A,单线程编程,那么就要考虑很多,建立整个程序模型比较麻烦。但是如果把这个大的任务A分解成几个小任务,任务B、任务C、任务D,分别建立程序模型,并通过多线程分别运行这几个任务,那就简单很多了。

标签:Java,并发,线程,内存,JMM,多线程,CPU
From: https://www.cnblogs.com/xswz/p/18577326

相关文章

  • Java 使用魔数判断文件类型
    引言在日常的开发工作中,一般是使用文案后缀去判断文件类型,这种不是很严谨,那么这样可通过修改文件名的方式去修改文件类型,如果将一个危险文件修成成png或者txt上传到文件服务器,后果难以估量。那么可以使用文件头魔数的方式去判断文件类型,这是一种比较安全的方式。魔数介绍(Magic......
  • 拥抱 OpenTelemetry:阿里云 Java Agent 演进实践
    作者:陈承背景在2018年的2月,ARMSJavaAgent的第一个版本正式发布,为用户提供无侵入的的可观测数据采集服务。6年后的今天,随着软件技术的迅猛发展、业务场景的逐渐丰富、用户规模的快速增长,我们逐渐发现过去的功能以及架构的设计逐渐难以合理、优雅的满足今天的需求,重构越来......
  • Java小白学习之---抽象类
    一、引出方法不知道怎么写,写了也没意义,不如写成抽象方法╮(╯3╰)╭所谓抽象方法就是没有实现的方法所谓没有实现就是指,没有方法体当一个类中存在抽象方法时,需要将该类声明为abstract类二、抽象类介绍用abstract关键字来修饰一个类时,这个类就叫抽象类【访问修饰符ab......
  • 这些 JavaScript 编码习惯,让你最大程度提高你的项目可维护性!
    前言:因为JavaScript语言是一门极其松散、极其自由的语言,这意味着我们可以随心所欲的操作它,这是他的优点,但同时也是它的缺点。在编码过程中,我们需要一种良好的规范或者习惯来保持应用程序的一致性和可维护性。而今天我们要说的就是,怎么在日常编码中通过一些的良好的编码习惯,从你......
  • java jvm部分命令 ~~还在完善中
    命令整理jps-q只输出进程号-mmain函数的参数-l主类全名-v输出jvm参数jstatjstat-gcpid100010classgcgccapacitygcutilgccausegcnewgcnewcapacitygcoldgcoldcapacitycompilerprintcompilationgcmetacapacityjinfo-syspropspid-fl......
  • Linux服务器部署java项目(一)
    前一阵子实验室的项目要部署在服务器上(ubuntu22.04),记录一下部署的过程1.jdk1.8安装解压安装包tar-zxvfjdk版本号加配置文件sudovim/etc/profile.d/my_env.sh#JAVA_HOMEexportJAVA_HOME=/opt/jdk1.8.0_191exportPATH=$PATH:$JAVA_HOME/bin测试是否安......
  • Java实现抢红包算法,附完整代码(公平版和手速版) 二倍均值算法 抢红包通用业务算法
     今天研究红包雨了解到二倍均值算法 微信发放100元10个红包随机的首先我们先看一下拼手气红包的功能要求: 所有红包累计金额等于红包总金额 每个红包金额不能小于0.01元,也就是说必须保证每个用户至少能抢到一个预设的最小金额,人民币红包设置的最小金额一般是0.01元,如果......
  • 使用Java导出excel内包含图片
    功能使用点最近公司需要开发一个数据表格导出excel的功能,普通的excel表格很好解决,网上有很多方法,下次写篇文章记录我的方法,但开发到有一个需求是excel是需要带图片的还是有些难度的,网上找了很多方案都无法适配,这里我记录下使用的方法。这里最后是在这篇文章上进行了优化,优化......
  • [Javascript] 等号运算符的运算和转换规则
    ==从上到下按照规则比较,直到能够得到确切结果为止:1.两端存在NaN,返回false2.undefined和null只有与自身比较,或者互相比较时,才会返回true,和其他原始类型比较返回false3.两端类型相同,比较值4.两端都是原始类型,转换成数字重新比较5.一端是原始类型,一端是对象类型,把对象......
  • 使用XWPFTemplate进行java后端word模版导出
    1.pom引入poi-tl<dependency><groupId>com.deepoove</groupId><artifactId>poi-tl</artifactId><version>1.7.3</version></dependency> 2.word模版 3.业务代码......