在之前的文章中,已经发布了常见的面试题,这里我花了点时间整理了一下对应的解答,由于个人能力有限,不一定完全到位,如果有解答的不合理的地方还请指点,在此谢过。

本文主要描述的是java多线程中面试的基本概念。这个在面试中一般不会直接问,但是如果对一些知识点敞开描述的时候,可以深入聊下。如果对java多线程感兴趣的同学可以看下公众号里多线程系列的文章,也许会对你有些帮助。

说下并发和并行的区别?

并发是指在一段时间内有多个任务需要执行,你可以使用单个cpu串行:在cpu在执行多个任务的时候,每个时间点都只能执行一个任务,但是每次执行的时间片很短(每个任务切换很快),导致用户感觉有多个任务在执行。也可以使用多个cpu并行:在不同的cpu上同时执行多个任务。

并行是指多个任务在同一个时间点由不同的cpu一起执行。并行是一种cpu真正实现并发的方式。它们是两个不同的层面的概念。

说下线程和进程的区别?了解过守护线程么?

进程是资源分配的最小单位,线程是CPU调度的最小单位。而守护线程是一种幕后的线程,其优先级别较低,一般完成的是系统性的服务,当系统中最后一个非守护线程结束的时候,守护线程也会和jvm一起结束。常见的守护线程是垃圾回收线程。

多线程的三个基本特性是什么?Java 是通过什么方式解决的?

并发的三大特性是:有序性、可见性、原子性。

有序性:指在java并发中,如果执行编码的两条指令按照代码的先后顺序执行。编译器,处理器为了提升执行效率会对代码编译过后的执行指令进行重新排序(指令重排序)。在as-if-serial中规定了执行重排序一定要满足执行的结果不受指令排序的影响,编译器和处理器都会遵守这个规则,但是as-if-serial是针对单线程的,它只定义了单线程下指令重排序不能影响执行结果,对于多线程的情况下,有可能会导致执行结果不可预料。为了解决有序性的问题,java提供了锁机制保障代码执行的先后顺序。

可见性:指在多线程的环境下,如果一个线程修改了堆里面的变量,另一个线程是否立即感知到。在java语言中,每个线程都保留了一份用到的变量在本地缓存,在主存中也有一份,其示意图如下,如何保证线程A修改之后,线程B也能感知,java提供了volatile,锁等机制来解决。

原子性:在执行一条指令的时候,对其他线程而言,要么执行成功,要么执行失败,没有中间状态。在保证原子性上,java提供了锁机制,atomic变量来保证。

线程的状态有哪些?它们是怎么转换的?Jvm使用什么指令查看线程状态?

一个线程从创建到结束要经过6个生命周期,在这六个生命周期中,分别有一些特别明显的标志来标识不同线程的状态,这6个生命周期分别是:

新建(NEW):我们在使用new的时候,创建了一个线程,这个创建出来的线程就是新建状态。这个状态类似于虚拟机给其他类创建一个对象一样,会给其分配一些内存空间。、

可运行(RUNNABLE):当我们对创建的线程,调用start函数的时候,这个时候该线程就处于就绪(READY),Java虚拟机会为该线程创建程序创建方法调用栈和程序计数器,等待调度运行等,当绪态的线程拿到了cpu之后,开始执行run函数里面的具体内容时,变成了运行态(RUN)。将这两个状态称为可运行状态。

等待(WAIT):等待状态的线程需要被显式唤醒,不然会一直等待。该状态的线程不能获取到CPU。

阻塞(BLOCKED):多个线程在进入临界区的时候排在外面等待进入临界区的线程,如果没有获取到锁会一直等待下去,所以在处理临界区代码的时候要尽量避免死锁。

超时等待(TIMED_WAITING):为了防止线程一直等待下去,设置了一个等待的时间,在等待时间未到的时候不能获取到CPU。

结束(TERMINATED):就是这个线程执行完了任务,或者遇到了没有捕获的异常,又或者主动关闭线程,那么这个线程的资源被收回,该线程也不会在占用cpu。

具体的状态转换图如下:

在jvm中,我们一般使用jstack -f pid >pid

简述一下JMM,as-if-serial语义,happens-before模型?

Java程序员希望java内存模型简单易懂,有很强的规则,而编译器,处理器则希望java内存模型没有那么多的规则,它们可以尽可能的优化代码的执行顺序。而JMM的设计就是为了平衡两者之差,在JMM中规定了只要不改变程序的执行结果(单线程和正确同步的多线程),编译器和处理器怎么优化都行。对程序员来说,JMM提供了happens-before模型来帮助理解java的内存可见性。Happens-before模型描述了两个操作的执行顺序,happens-before关系定义如下:

  1. 如果一个操作happens-before另一个操作,那么第一个操作的执行结果将对第二个操作可见,而且第一个操作的执行顺序排在第二个操作之前。

2)两个操作之间存在happens-before关系,并不意味着Java平台的具体实现必须要按照 happens-before关系指定的顺序来执行。如果重排序之后的执行结果,与按happens-before关系来执行的结果一致,那么这种重排序并不非法(也就是说,JMM允许这种重排序)

根据这两条定义,其规定了几个基本的执行规则:

  1. 程序次序规则:一个线程内,按照代码顺序,书写在前面的操作先行发生于书写在后面的操作;
  2. 锁定规则:一个unLock操作先行发生于后面对同一个锁额lock操作;
  3. volatile变量规则:对一个变量的写操作先行发生于后面对这个变量的读操作;
  4. 传递规则:如果操作A先行发生于操作B,而操作B又先行发生于操作C,则可以得出操作A先行发生于操作C;
  5. 线程启动规则:Thread对象的start()方法先行发生于此线程的每个一个动作;
  6. 线程中断规则:对线程interrupt()方法的调用先行发生于被中断线程的代码检测到中断事件的发生;
  7. 线程终结规则:线程中所有的操作都先行发生于线程的终止检测,我们可以通过Thread.join()方法结束、Thread.isAlive()的返回值手段检测到线程已经终止执行;
  8. 对象终结规则:一个对象的初始化完成先行发生于他的finalize()方法的开始;

相比于happens-before模型,as-if-serial语义则是描述的单线程的内存可见性问题。该语义规定了不管怎么重排序(编译器和处理器为了提高并行度),在单线程的情况下,程序的执行结果不能被改变。为了实现as-if-serial语义,编译器和处理器必须要满足数据依赖性原则。数据依赖性描述的是如果一个语句的执行结果依赖于上面某条语句的执行结果,那么这两个语句就不能被重排序。

了解过死锁么?解决死锁的方法有哪些?

发生死锁有以下4个前提条件:

互斥条件:进程对于所分配到的资源具有排它性,即一个资源只能被一个进程占用,直到被该进程释放

请求和保持条件:一个进程因请求被占用资源而发生阻塞时,对已获得的资源保持不放。

不剥夺条件:任何一个资源在没被该进程释放之前,任何其他进程都无法对他剥夺占用

循环等待条件:当发生死锁时,所等待的进程必定会形成一个环路(类似于死循环),造成永久阻塞。

当以上四个条件满足的时候,就会发生死锁,死锁的解决方案一般是预防,检测,避免。常见的有超时机制(破坏第四个条件),innodb中会使用死锁检测来避免死锁问题。

CAS了解过么?

CAS本身compareAndSwap的缩写,其实现原理是通过比较当前值是否是预期值,如果是预期值的话,原子性的更新值。在这个过程中,有几个关键的参数,当前值(Current),预期值(Expect),更新后的值(New)。那么其具体的实现原理如下:

Cas的一个重大优势是不加锁,增大并发。但是其也存在弊端:

  1. ABA问题:当一个线程读出的值是C,在更新E=C的过程中,如果另一个线程将C 的值改变,那么这样更新肯定会失败,但是如果另一个线程将C的值改变后又将C的值变回来,那么这个时候当前线程是无法感知到原来的C值已经发生了变化,换句话说就是这个线程是无法感知到另一个线程在那段时间的操作,所以最后校验值的时候发现是一样的,所以也会更新成功。这就是经典的ABA问题,就是一个线程将C值A改成B之后,又将该值该回了A,更新的那个线程如果只是判断A值是否存在的话,那样有可能就会有问题。那么ABA在实际中会带来哪些问题呢?举个例子,我们在CAS时,使用的是一个数组的长度进行判断,如果我们认为数组的长度没有发生变化的话,我们就可以继续添加值,但是在这里的话,有可能数组的内容发生了改变,这样就导致了可能发生错误了。当然了,ABA问题也不是不可以避免的,在实际中,往往通过加一个version号来表示当前的版本的版本,每次在更新的时候,版本就依次往上加1,那样ABA就会变成1A-》2B-》3A,这样的一个过程就很容器判断是否是原来的A了。
  2. 线程空转:这个从上面的流程图中很容易就理解了,通过自旋不断判断的话,当然会导致cpu上升,并且这种空转在大多数的时候是无效的。

3)只能保证一个共享变量的原子操作:当对一个共享变量执行操作时,我们可以使用循 环CAS的方式来保证原子操作,但是对多个共享变量操作时,循环CAS就无法保证操作的原子 性,这个时候就可以用锁

缓存一致性协议了解么?

由于cpu的执行速度远远大于IO的速度,为了减少和IO的交互,增高效率,cpu内部会有高速缓存(cache)。当程序运行的时候,高速缓存中会从主存中保存一份副本数据。每次读写都在高速缓存中操作,这个在单线程下是没有问题的,但是多线程下会导致数据不一致的情况(其他线程中的数据没有同步该线程修改的数据)。为了解决这个问题(其实就是上图中可见性描述),通常有两种方案进行解决:锁和缓存一致性协议。由于在总线上加锁的机制导致效率低下,所以缓存一致性协议就变得关键了。具体原理是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。

本文的内容就这么多,如果你觉得对你的学习和面试有些帮助,帮忙点个赞或者转发一下哈,谢谢。

想要了解更多java内容(包含大厂面试题和题解)可以关注公众号,也可以在公众号留言,帮忙内推阿里、腾讯等互联网大厂哈

Java多线程篇--基本概念相关推荐

  1. 面试题汇总二 Java 多线程篇

    前言 题目汇总来源 史上最全各类面试题汇总,没有之一,不接受反驳 面试题汇总一 Java 语言基础篇 面试题汇总二 Java 多线程篇 面试题汇总三 Java 集合篇 面试题汇总四 JVM 篇 面试题 ...

  2. java 多线程的基本概念_java基本教程之多线程基本概念 java多线程教程

    多线程是Java中不可避免的一个重要主体.下面我们将展开对多线程的学习.接下来的内容,是对"JDK中新增JUC包"之前的Java多线程内容的讲解,涉及到的内容包括,Object类中 ...

  3. Java多线程上——基本概念及操作

    目录 多线程定义: 多线程编程 创建线程方法 Thread 类及常见方法 启动问题(start() 与 run()) 区别 中断线程 等待一个线程-join() 线程的状态 线程安全 线程安全定义 线 ...

  4. Java多线程-线程的概念和创建

    前言 声明:该文章中所有测试都是在JDK1.8的环境下. 该文章是我在学习Java中的多线程这方面知识时,做的一些总结和记录. 如果有不正确的地方请大家多多包涵并作出指点,谢谢! 一.基础概念 我们知 ...

  5. Java多线程-锁的概念

    1.结婚戒指的意义 根据文献记载,最早使用戒指人就是希腊的悲剧英雄--被缚的普罗米修斯.宙斯为惩罚普罗米修斯盗火给人类,将他绑缚在考卡苏斯山上,每天都有一只老鹰飞到山上,将他的内脏啄出,到了夜晚,他所 ...

  6. java多线程编程01---------基本概念

    一. java多线程编程基本概念--------基本概念 java多线程可以说是java基础中相对较难的部分,尤其是对于小白,次一系列文章的将会对多线程编程及其原理进行介绍,希望对正在多线程中碰壁的小 ...

  7. Java总结篇系列:Java多线程(二)

    本文承接上一篇文章<Java总结篇系列:Java多线程(一)>. 四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型.下面分别看下引起Java线程阻塞的主要方法 ...

  8. JAVA多线程基础篇-关键字synchronized

    1.概述 syncronized是JAVA多线程开发中一个重要的知识点,涉及到多线程开发,多多少少都使用过.那么syncronized底层是如何实现的?为什么加了它就能实现资源串行访问?本文将基于上述 ...

  9. Java太密来福_这篇文章就是要让你入门java多线程【多线程入门】-Go语言中文社区...

    就在前几天,有位读者朋友私信宜春,说期待出一篇多线程的文章,我当时内心是小鹿乱撞啊-于是这几天茶不思饭不想,好几天深夜皆是辗转反侧,两目深凝,以至于这几天走起路来格外飘飘然,左摇右晃的,魔鬼般的步伐, ...

  10. 别翻了,这篇文章就是要让你入门java多线程!

    目录 1. 理解线程与进程 2.理解并行和并发 3.特殊的一个单线程:主线程(Main线程) 4. 创建多线程的四种方式 5.使用匿名内部类方式创建线程 6.线程安全问题 7.解决线程安全问题:线程同 ...

最新文章

  1. NLP(2) | 中文分词分词的概念分词方法分类CRFHMM分词
  2. 电子绘本pdf_我不是完美小孩电子绘本pdf
  3. 相对最完整的软件测试工具手册
  4. [iOS]关于零基础学习iOS开发的学习方法总结
  5. boost::geometry模块自定义多边形示例
  6. Mybatis源码之与Spring集成包
  7. c语言创建文件的作用,c语言文件创建与建立
  8. MFC开发IM-第十篇、MFC改变static text颜色
  9. Box2D——入门教程
  10. framework7的改进,以及与vue组合使用遇到的问题以及解决方法 (附vue的原理)
  11. XML DOM学习笔记(JS)
  12. 算法笔记_010:插入排序(Java)
  13. WINDOWS下线程同步探讨
  14. sysrq 和 sysrq-trigger
  15. 数据分析师职业发展的几个层次,具体是什么做什么的
  16. 3.1 电磁干扰EMI
  17. 【IMWeb训练营作业】- 作业3:仿readhub.me
  18. 【期末大作业】公益网站ps平面设计
  19. 入职体检(三甲医院)
  20. visual studio 2008微软教程

热门文章

  1. zabbix web监控 一: zabbix3.2添加web页面监控(Web monitoring)
  2. 我们是怎么简单打开百度的?
  3. 安全 | 开源入侵防御系统 Snort
  4. react-redux中Connect方法
  5. Java程序打包成jar文件
  6. 地理信息系统(Geographic Information System或 Geo-Information system,GIS)
  7. 华硕bios更改固态硬盘启动_华硕bios如何设置固态硬盘启动?
  8. python 对象的销毁_销毁类python的对象
  9. 事务里面的脏读、不可重复读、虚读/幻读
  10. 关于u8的三种备份方式