Java并发自测题

news2024/10/6 8:37:19

文章目录

  • 一、什么是线程和进程?线程与进程的关系,区别及优缺点?
  • 二、为什么要使用多线程呢?
  • 三、说说线程的生命周期和状态?
  • 四、什么是线程死锁?如何预防和避免线程死锁?
  • 五、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 原子类

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


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1830175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Android 自定义View

我们所有的试图都是起源于自定义View,包括ViewGroup也是继承于它,可以说它是视图组件之父。 我们可以从它的大致流程来分为四个部分: 构造方法,onMeasure,onLayout,onDraw 构造方法: 它主要有…

Java | Leetcode Java题解之第160题相交链表

题目: 题解: public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if (headA null || headB null) {return null;}ListNode pA headA, pB headB;while (pA ! pB) {pA pA null ? headB : pA.next;pB …

Springmvc接收请求参数

如果你觉得这种限制很麻烦,你可以改为String 因为所有参数在接收的时候原值都是字符串

Mac | 崩溃分析

一、dump分析 1. 导入符号: ./import_pdb.sh libmedia_stream_ext.dylib.dSYM ./import_pdb.sh libowcr.framework.dSYM 2. 分析dump: ./analyze_dump.sh AE59D64F-0E1D-4A18-8DAF-C2C4D22F9FA6.dmp 3. 第 2 步骤 中会输出崩溃模块、崩溃线程及堆栈…

使用 Python 进行测试(5)测试的类型

总结 和我一起唱! 冒烟测试,让你快速失败; 回归测试,不打破过去; 健全性检查,保留所拥有; 集成测试,处理副作用; 端到端,永无尽头! 回测&#xf…

SwiftUI 6.0(Xcode 16)全新 @Entry 和 @Previewable 宏让开发妙趣横生

概览 如火如荼的 WWDC 2024 已进入第五天,苹果开发平台中众多海量新功能都争先恐后的喷薄欲出。 在这里就让我们从中挑两个轻松有趣的新功能展示给小伙伴们吧:它们分别是 全新的 Entry 和 Previewable 宏。 在本篇博文中,您将学到如下内容&a…

用React编写一个密码组件表单

theme: condensed-night-purple highlight: atelier-cave-light 背景介绍 我们在使用网站或者应用程序的登录界面或创建帐户界面时,往往避免不了需要用户输入密码这一步骤,而用户是否可以选择看见他们输入的密码是十分重要的一项功能。尤其是在当输入的…

Focusky是什么软件

Focusky是一款基于HTML5技术的多媒体演示软件,可以轻松地制作出生动有趣的PPT演示文稿、动画宣传片以及微课。与其他软件相比,Focusky拥有丰富的多媒体资源和动画效果,可以让演示内容更加生动。本文将为您详细介绍Focusky软件的功能&#xff…

awd工具安装

fscan(漏洞扫描) 下载 下载地址: Releases shadow1ng/fscan GitHub 把下载的文件放到指定文件目录里, 在文件的位置打开cmd 输入 fscan64.exe -h 192.168.1.1/24 ok了 接下来说说fscan的使用 使用 1.信息搜集: 存活探测(icmp) 端口扫描 2.爆破功能: 各类服务爆破(…

MongoDB~高可用集群介绍:复制集群(副本集)、分片集群

背景 MongoDB 的集群主要包括副本集(Replica Set)和分片集群(Sharded Cluster)两种类型。 副本集 组成:通常由一个主节点(Primary)和多个从节点(Secondary)构成。 功…

UniVue更新日志:使用ObservableList优化LoopList/LoopGrid组件的使用

github仓库 稳定版本仓库:https://github.com/Avalon712/UniVue 开发版本仓库:https://github.com/Avalon712/UniVue-Develop UniVue扩展框架-UniVue源生成器仓库:https://github.com/Avalon712/UniVue-SourceGenerator 更新说明 如果大家…

Django REST framework视图集与路由详解:深入理解ViewSet、ModelViewSet与路由映射器

系列文章目录 Django入门全攻略:从零搭建你的第一个Web项目Django ORM入门指南:从概念到实践,掌握模型创建、迁移与视图操作Django ORM实战:模型字段与元选项配置,以及链式过滤与QF查询详解Django ORM深度游&#xff…

【java】数学运算考试系统

目录 一、登录界面: 二、管理员界面: 三、学生考试界面: 面向小学低年级学生,随机生成两个整数的加减法算式要求学生解答。要求有用 户登录、注册等 GUI 界面,用户数据存入文件,体现面向对象编程思想。 …

windows11子系统Ubuntu 22.04.4子安装图形化界面

1、windows11家庭版本设置 打开虚拟机安装许可 2、Microsoft Store下载安装ubuntu 我使用的是22.04.4 LTS版本 3、 打开ubuntu 命令窗口 1、打开win11的命令行,在下拉三角下标,打开,可以看到有Ubuntu 的选项,点击即可进入linux命…

【Android面试八股文】你说一说什么是双亲委托机制?为什么需要双亲委托机制?

一、双亲委托机制 1.1 双亲委托机制概述 双亲委托机制是指当一个类加载器收到一个类加载请求时, 该类加载器首先会把请求委派给父类加载器。 如果父类加载器还存在父类加载器,则会一直向上委派,直至最终交由顶层的启动类加载器完成类加载, 每个类加载器都是如此,只有在所…

RIP解决不连续子网问题

#交换设备 RIP解决不连续子网问题 一、不连续子网的概念 相同主网下的子网,被另一个主网分割,例如下面实验拓扑在某公司的网络整改项目中,原先R1 和RS 属于同一主网络 10.0.0.0/8,现被 R2、R3、R4 分离,整网采用了 …

Docker 安装 MySQL5.7 和 MySQL8

文章目录 安装 MySQL5.7拉取镜像前期准备启动容器 安装MySQL8.0拉取镜像查看镜像前期准备启动容器 安装 MySQL5.7 拉取镜像 docker pull mysql:5.7拉下来镜像后 执行 docker images 此时我们已经有这个镜像了。 前期准备 在根目录下创建 app , 在 app 目录下创建…

牛客周赛 Round 47 解题报告 | 珂学家

前言 题解 这真的是牛客周赛? 哭了 欢迎关注 珂朵莉 牛客周赛专栏 珂朵莉 牛客小白月赛专栏 A. 小红的葫芦 签到题 但是写起来有点变扭,方法应该蛮多的 统计分组 有2组一组长度为2,一组长度为3 def check(arr):arr.sort()if arr[0] …

数据结构试题 20-21

真需要就死记吧 二叉树遍历-先序(非递归)【图解代码】_哔哩哔哩_bilibili 解释一下步骤: 一个循环为: 1.取节点 2.放右子树 3.放左子树 每次循环,都要从栈里取出一个节点 先放右子树,再放左子树 那这道题就是,先放1&am…

内网Docker镜像无法使用?Debian/Ubuntu离线安装Dokcer

离线安装Docker 卸载冲突的包 for pkg in docker.io docker-doc docker-compose podman-docker containerd runc; do sudo apt-get remove $pkg; done先删除docker sudo apt-get purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin d…