Java并发自测题

2024-06-16 21:28
文章标签 java 并发 自测题

本文主要是介绍Java并发自测题,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 一、什么是线程和进程?线程与进程的关系,区别及优缺点?
  • 二、为什么要使用多线程呢?
  • 三、说说线程的生命周期和状态?
  • 四、什么是线程死锁?如何预防和避免线程死锁?
  • 五、synchronized 关键字
  • 六、并发编程的三个重要特性
  • 七、JMM (Java Memory Model,Java 内存模型)和 happens-before 原则。
  • 八、volatile 关键字
  • 九、ThreadLocal 关键字
  • 十、ReentrantLock 和 AQS
  • 十一、乐观锁和悲观锁的区别
  • 十一、CAS 了解么?原理?什么是 ABA 问题?ABA 问题怎么解决?
  • 十二、Atomic 原子类


一、什么是线程和进程?线程与进程的关系,区别及优缺点?

提示:可以从从 JVM ⻆度说进程和线程之间的关系
首先说进程,进程其实就是程序的一次执行的过程。而线程与进程相似但是线程是比进程更小的单位。一个进程在其执行的过程中可以产生多个线程。线程是程序内部的一条执行路径,是程序中的一个单一的顺序控制流程。可以认为是进程里的一条执行路径。

区别:
在这里插入图片描述
从上图可以看出:一个进程中可以有多个线程,多个线程共享进程的堆和方法区 (JDK1.8 之后的元空间)资源,但是每个线程有自己的程序计数器、虚拟机栈 和 本地方法栈。

总结: 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,因为同一进程中的线程极有可能会相互影响。线程执行开销小,但不利于资源的管理和保护;而进程正相反。


二、为什么要使用多线程呢?

提示:从计算机⻆度来说主要是为了充分利⽤多核 CPU 的能⼒,从项⽬⻆度来说主要是为了提升系统的性能。

首先我们从计算机底层来说,线程可以比作是轻量级的进程,是程序执行的最小单位,线程之间的切换和调度的成本远远小于进程。另外,多核cpu时代意味着多个线程可以同时运行,这减少了线程上下文切换的开销。其次对于现在互联网发展的趋势来说, 现在的系统动不动就要求百万级甚至千万级的并发量,而多线程并发编程正是开发高并发系统的基础,利用好多线程机制可以大大提高系统整体的并发能力以及性能。


三、说说线程的生命周期和状态?

提示: 6 种状态( NEW 、 RUNNABLE 、 BLOCKED 、 WAITING 、 TIME_WAITING 、 TERMINATE D )。

线程的生命周期是由六种不同的状态的,首先线程被创建变为初始状态,线程调用start方法变成运行状态,在运行会发生阻塞或者等待,其中等待状态有两种分别是等待状态和超时等待状态,其中等待状态是表示该线程需要等待其他线程做出一些特定动作(通知或中断)。超时等待状态是在指定的时间后自行返回而不是像等待那样一直等待。阻塞状态是需要等待锁释放。最后是终止状态,表示该线程已经运行完毕了。


四、什么是线程死锁?如何预防和避免线程死锁?

这⾥最好能够结合代码来聊,你要确保⾃⼰可以写出有死锁问题的代码。

所谓线程死锁其实就是多个线程同时被阻塞,它们中的一个或者其他全部都在等待某个资源释放。由于线程无限期被阻塞,因此程序不能正常被终止。

其实预防死锁的方式只需要破坏产生死锁的必要条件即可,第一个破坏请求与保持条件(一次性申请所有的资源),第二个破坏不可剥夺条件(占用部分资源的线程进一步申请其他资源时,如果申请不到,可以主动释放它所占有的资源),第三个破坏循环等待条件(靠按序申请资源来预防。按某一顺序申请资源,释放资源则反序释放。破坏循环等待条件。)

避免死锁就是在资源分配时,借助于算法(比如银行家算法)对资源分配进行计算评估,使其进入安全状态。


五、synchronized 关键字

提示: synchronized 关键字⼏乎是⾯试必问,你需要搞懂下⾯这些 synchronized 关键字相关的问题: 1.synchronized 关键字的作⽤,⾃⼰是怎么使⽤的。2.synchronized 关键字的底层原理(重点!!!)3.JDK1.6 之后的 synchronized 关键字底层做了哪些优化。 synchronized 锁升级流程。4.synchronized 和 ReentrantLock 的区别。5.synchronized 和 volatile 的区别。

首先,synchronized关键字翻译成中文是同步的意思,主要解决的是多个线程之间访问资源的同步性,被它修饰的方法或者代码块在任意时刻只能有一个线程执行。该关键字的使用方式主要用于三个地方分别是:1.修饰实例方法 2.修饰静态方法 3.修饰代码块

底层原理 跟JVM中的对象监视器 monitor 有关。
synchronized 同步语句块的实现使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。
synchronized 修饰的方法并没有 monitorenter 指令和 monitorexit 指令,取得代之的确实是 ACC_SYNCHRONIZED 标识,该标识指明了该方法是一个同步方法。

.synchronized 和 ReentrantLock 的区别:ReentrantLock 实现了 Lock 接口,是一个可重入且独占式的锁,和 synchronized 关键字类似。不过,ReentrantLock 更灵活、更强大,增加了轮询、超时、中断、公平锁和非公平锁等高级功能。

synchronized 与volatile 区别在于,它们两个关键字是互补的存在,volatile 关键字是线程同步的轻量级实现,所以 volatile性能肯定比synchronized关键字要好 。但是 volatile 关键字只能用于变量synchronized 关键字可以修饰方法以及代码块 。其次volatile 关键字可以保证数据的可见性,但不能办证数据的原子性。Synchronized都可以保证。volatile关键字主要用于解决变量在多个线程之间的可见性,而 synchronized 关键字解决的是多个线程之间访问资源的同步性


六、并发编程的三个重要特性

提示: 原⼦性、可⻅性、有序性
分别是原子性、可见性、有序性。原子性是一次操作或者多次操作,要么所有的操作全部都得到执行并且不会受到任何因素的干扰而中断,要么都不执行。在 Java 中,可以借助synchronized、各种 Lock 以及各种原子类实现原子性。synchronized 和各种 Lock 可以保证任一时刻只有一个线程访问该代码块,因此可以保障原子性。
可见性是当一个线程对共享变量进行了修改,那么另外的线程都是立即可以看到修改后的最新的值的。
有序性是保证指令不会受cpu指令并行优化(指令重排)的影响,由于指令重排序问题,代码的执行顺序未必就是编写代码时候的顺序。


七、JMM (Java Memory Model,Java 内存模型)和 happens-before 原则。

JMM模型是java内存模型,可以把 JMM 看作是 Java 定义的并发编程相关的一组规范,除了抽象了线程和主内存之间的关系之外,其还规定了从 Java 源代码到 CPU 可执行指令的这个转化过程要遵守哪些和并发相关的原则和规范,其主要目的是为了简化多线程编程,增强程序可移植性的。
happens-before 原则是一种规则,用于区分事件发生的前后顺序。


八、volatile 关键字

提示: volatile 关键字同样是⼀个重点!结合 JMM (Java Memory Model,Java 内存模型)和 happens-before 原则来回答就⾏了。

volatile 关键字能保证数据的可见性,但不能保证数据的原子性。synchronized 关键字两者都能保证。


九、ThreadLocal 关键字

提示:关注 ThreadLocal 的底层原理、内存泄露问题以及⾃⼰是如何在项⽬中使⽤ ThreadLocal 关键字的。

通常情况下,我们创建的变量是可以被任何一个线程访问并修改的。如果想实现每一个线程都有自己的专属本地变量该如何解决呢?

JDK 中自带的ThreadLocal类正是为了解决这样的问题。 ThreadLocal类主要解决的就是让每个线程绑定自己的值,可以将ThreadLocal类形象的比喻成存放数据的盒子,盒子中可以存储每个线程的私有数据。ThreadLocal 就是用来避免这两个线程竞争的。


十、ReentrantLock 和 AQS

提示: ReentrantLock 的特性、实现原理(基于 AQS )。可以从 ReentrantLock 的实现来理解 AQS

ReentrantLock 和 AbstractQueuedSynchronizer(AQS) 是 Java 并发编程中的重要概念。
ReentrantLock 是一个可重入的互斥锁,由 Java 并发包中的 java.util.concurrent.locks.ReentrantLock 类实现。"可重入"意味着一个线程可以多次获取同一把锁,这在需要多次进入临界区的情况下非常有用。ReentrantLock 提供了与 synchronized 关键字类似的功能,但比 synchronized 更加灵活,因为它可以尝试获取锁(如果锁不可用,那么立即返回,而不是阻塞),并且可以中断等待锁的线程。
AbstractQueuedSynchronizer(AQS) 是 Java 并发包中的一个框架,用于构建依赖于先进先出 (FIFO) 等待队列的阻塞锁和相关同步器(信号量,事件,等待/通知等)。它使用一个整数状态表示获取或释放锁,子类需要定义改变这个状态的方法。ReentrantLock 就是基于 AQS 实现的。
AQS 通过内部的 FIFO 队列来管理阻塞的线程。如果请求的锁没有被其他线程持有,那么请求的线程可以成功获取锁;否则,这个线程就会被放入队列中,直到有其他线程释放锁为止。
总的来说,ReentrantLock 和 AQS 都是构建高效并发应用的重要工具,它们提供了一种更细粒度的锁控制方式,使得开发者能够更好地控制并发行为。


十一、乐观锁和悲观锁的区别

悲观锁::悲观锁在操作数据时比较悲观,认为别人会同时修改数据。因此操作数据时直接把数据锁住,直到操作完成后才会释放锁;上锁期间其他人不能修改数据。

乐观锁:乐观锁在操作数据时非常乐观,认为别人不会同时修改数据。因此乐观锁不会上锁,只是在执行更新的时候判断一下在此期间别人是否修改了数据:如果别人修改了数据则放弃操作,否则执行操作。


十一、CAS 了解么?原理?什么是 ABA 问题?ABA 问题怎么解决?

提示:多地⽅都⽤到了 CAS ⽐如 ConcurrentHashMap 采⽤ CAS 和 synchronized 来保证并发安全,再⽐如 java.util.concurrent.atomic 包中的类通过 volatile+CAS 重试保证线程安全性。和⾯试官聊 CAS 的时候,你可以结合 CAS 的⼀些实际应⽤来说。

CAS,全称Compare And Swap,是一种无锁算法。在不使用传统锁的情况下,它通过比较内存中的值和预期值来决定是否更新内存中的值。基本操作是这样的:它包含三个参数CAS(V,E,N),V表示要更新的变量,E表示预期值,N表示新值。如果V值等于E值,则将V的值设为N。如果V值与E值不相等,则说明其他某个线程已经改变了V的值,那么本次操作就会失败。

ABA问题是CAS操作中可能会遇到的一个问题。假设V原来的值是A,它被线程1获取,就在这时,线程2也访问了V,将V的值由A改成B,然后又改回A,此时线程1进行CAS操作发现V的值仍然为A,然后线程1以为V的值没有被修改过,然后进行CAS操作,但实际上,V的值已经被线程2改变过了,这就是所谓的ABA问题。

对于ABA问题,一个常见的解决方案是使用版本号。在每次变量更新的时候,都把版本号加一,这样,即使A变成B,然后又变回A,版本号也会改变,这样就可以防止ABA问题。在Java中,AtomicStampedReference类就实现了这样的功能,它通过包装[E, S]对进行操作,其中E表示预期值,S表示版本号。当设置某个值时,它不仅检查值是否匹配,还会检查版本号是否也匹配,只有两者都匹配才会执行相应的操作。


十二、Atomic 原子类

原子类说简单点就是具有原子/原子操作特征的类。


这篇关于Java并发自测题的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1067593

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

Java中Redisson 的原理深度解析

《Java中Redisson的原理深度解析》Redisson是一个高性能的Redis客户端,它通过将Redis数据结构映射为Java对象和分布式对象,实现了在Java应用中方便地使用Redis,本文... 目录前言一、核心设计理念二、核心架构与通信层1. 基于 Netty 的异步非阻塞通信2. 编解码器三、

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

Java中的.close()举例详解

《Java中的.close()举例详解》.close()方法只适用于通过window.open()打开的弹出窗口,对于浏览器的主窗口,如果没有得到用户允许是不能关闭的,:本文主要介绍Java中的.... 目录当你遇到以下三种情况时,一定要记得使用 .close():用法作用举例如何判断代码中的 input

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S