【两万字面试系列】三年前的面试题。Service里面的线程安全问题

前言

三年前,大概是21年,那会刚学完java,然后去面试,被打的一塌糊涂,今天来盘一盘之前的面试,到底是怎样的问题整住了。然后发现了去年整的线程安全东西,也贴到文章后面了。那个贴的还不太准,慢慢完善!会整完然后发B站视频。
在这里插入图片描述

线程安全

其实简单的来看就是线程安全的问题。现在来看这些问题好像没有什么,就是比较正常的问题。但是当时掌握的确实太不好了,然后可能面试官看我太菜了,这些回答不上来就没有接着往后续问了。大家看到这个面试题会想到什么呢,会想怎么回答和解决呢。
也可以结合一个实际的项目区演示和测试一番。写一个数字的成员变逻辑写计算然后看结果。

在Spring Boot中,处理Service层的线程安全问题是非常重要的,因为Spring的Service默认是单例的,这意味着Spring容器中只会创建一个Service实例。如果Service中包含了状态(即成员变量),那么在并发环境下可能会出现线程安全问题。以下是一些处理Service层线程安全问题的建议:

  1. 避免在Service中定义有状态的成员变量

尽量不要在Service中定义有状态的成员变量。如果确实需要存储状态,考虑将这些状态存储在方法内部的局部变量中,因为局部变量是线程安全的,它们存储在每个线程自己的栈中。
2. 使用线程安全的类

如果Service需要维护跨方法调用的状态,应该使用线程安全的类或数据结构,如ConcurrentHashMap、AtomicInteger等。
3. 同步访问共享资源(使用锁机制)

当多个线程需要访问同一个资源时,可以通过同步机制来保证线程安全。可以使用synchronized关键字或java.util.concurrent.locks包中的锁机制。但是,过度同步可能会导致性能问题,因此需要谨慎使用。
4. 使用ThreadLocal

ThreadLocal可以为每个线程提供一个变量的副本,使每个线程都有自己独立的变量副本,从而避免线程安全问题。但是,使用ThreadLocal时需要注意及时清理,避免内存泄漏。

  1. 使用@Scope注解(不建议)

如果确实需要Service有状态,可以考虑使用Spring的@Scope注解来改变Bean的作用域。例如,使用@Scope(“prototype”)注解可以让Spring容器为每个请求创建一个新的Service实例,这样可以避免多个请求共享同一个Service实例的线程安全问题。但这种方式会增加对象的创建和销毁的开销。

线程安全

在这里插入图片描述

后面是自己写的,还不是很完善,会补充的完善,然后B站发视频

3.线程方面

3.1线程安全
3.1. spring如何处理线程并发问题

spring的对象是默认是单例的。如果在里面声明成员变量的话。然后一个请求创建一个线程,多个线程同时请求一个资源就会出现问题。(单例bean是线程安全的)

解决方式有两种

1.将spring声明成多例

2.使用threadloacal

3.在代码块中加入同步锁 让他编程同步的 就可以解决了

相当于把并行编程了串行,会影响服务器他吞吐量。

4.成员变量声明在方法里面

3.2 tomcat线程模型

tomcat也已经支持异步了;但是他的效率比netty这种肯定还是要低的。

BIO :tomcat6默认采用的。每个请求都要创建一个线程来处理,线程开销较大,不能处理高并发

3.4 Volatile

涉及到可见性 ,禁止重排序

volatile与cas 通过乐观锁的思想来共同完成相应的reenTrankllock,具体在锁那块3.4里面有

3.5 Servlet

单实例 ,多线程

3.6 ThreadLocal

以空间换时间,给每个线程分配一个空间

ThreadLocal 是Java里一种特殊的变量。每个线程都有一个 ThreadLocal 就是每个线程都拥有了自己独立的一个变量,竞争条件被彻底消除了。如果为每个线程提供一个自己独有的变量拷贝,将大大提高效率。首先,通过复用减少了代价高昂的对象的创建个数。其次,你在没有使用高代价的同步或者不变性的情况下获得了线程安全。

3.7 ThreadLocal可能引发内存泄漏问题

1、强引用(StrongReference)
最普遍的一种引用方式,如String s = “abc”,变量s就是字符串“abc”的强引用,只要强引用存在,则垃圾回收器就不会回收这个对象。
2、软引用(SoftReference)
用于描述还有用但非必须的对象,如果内存足够,不回收,如果内存不足,则回收。一般用于实现内存敏感的高速缓存,软引用可以和引用队列ReferenceQueue联合使用,如果软引用的对象被垃圾回收,JVM就会把这个软引用加入到与之关联的引用队列中。
3、弱引用(WeakReference)
弱引用和软引用大致相同,弱引用与软引用的区别在于:只具有弱引用的对象拥有更短暂的生命周期。在垃圾回收器线程扫描它所管辖的内存区域的过程中,一旦发现了只具有弱引用的对象,不管当前内存空间足够与否,都会回收它的内存。当一个对象既有弱引用又有强引用的时候不会清楚弱引用。短时间内通过弱引用取对应的数据,可以取到,当执行过第二次垃圾回收时,将返回null。弱引用主要用于监控对象是否已经被垃圾回收器标记为即将回收的垃圾,可以通过弱引用的isEnQueued方法返回对象是否被垃圾回收器标记。
ThreadLocal采用的是弱引用的key,当没有强引用来使用Thread Local的key时,key就会被回收。当我把ThreadLocal比作一个水桶,水桶上面有一个桶盖,我们在寻找桶的时候通过桶盖来寻找,但是当没有人惦记桶的时候,桶盖会自己丢失,这样我们没办法找到桶,也没法使用桶里的东西,这样就会导致内存泄漏。

 static class ThreadLocalMap {static class Entry extends WeakReference<ThreadLocal<?>> {/** The value associated with this ThreadLocal. */Object value;Entry(ThreadLocal<?> k, Object v) {super(k);value = v;}}}
	TreadLocalMap的Entry继承了WeakReference<ThreadLocal<?>>,即Entry的key是弱引用(该引用只存在弱引用的情况下,下一次GC]

ThreadLocal在保存的时候会把自己当做Key存在ThreadLocalMap中,正常情况应该是key和value都应该被外界强引用才对,但是现在key被设计成WeakReference弱引用了。

ThreadLocal的 key若引用 容易被GC回收,然后变成null。导入里面的 值没法被访问到,容易产生内存泄漏

3、解决方法

想象情况:如果一个线程被回收了,然后线程里面的成员变量也被回收,就没有内存泄漏的问题了。

实际情况:一般使用线程池,线程池是重复利用的,会存在内存泄漏的问题。ThreadLocal在进行数据读写的时候默认会进行一些清理的操作,找到并清理Entry里面key 为null 的数据

这个没有太好的解决方案,只能通过规范代码使用来解决最好是每次使用完ThreadLocal后,主动调用remove 方法去移除数据,把ThreadLocal 声明成全局变量,使他无法被GC回收

所以为了避免内存泄漏,在ThreadLocal使用结束以后,规范操作,执行下remove方法。

或者你可以从ThreadLocal,引出底层的Weak引用话题,再引出JVM结构以及OOM调优方面的话题。*

3.2 main方法线程(jvm创建线程过程)

一个程序创建一个jvm实例,一个进程,然后开辟一个线程

img

程序运行

JVM 在启动的时候会创建一个 VM Thread,这是所有线程的祖先,其他的线程都是由这个线程派生出去的。

在 Java 中,线程分为两种:普通线程守护线程

普通线程就是通常业务逻辑执行的代码,代码执行完成之后,普通线程也就退出了。而守护线程一般运行在后台,比如说响应命令行的操作,守护线程会在普通线程退出之后退出。

当程序执行完成之后,JVM 也要退出,程序执行完的标志就是非守护线程都退出了。当所有的非守护线程退出之后,守护线程也会退出。

程序在执行完成之后,会调用 System.exit() 方法,然后虚拟机退出,程序彻底结束。

exit 方法接收一个整型的参数,如果传入的值为 0,那么就表示程序是正常退出的,如果是任何非零的值,那么就表示是异常退出。

其实在代码中,非常不推荐调用这个方法,因为这个方法会造成一些意向不到的情况。

作者:Rayjun
链接:https://juejin.cn/post/6866744930376220679
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

3.3线程池

线程池的几个参数

包括阻塞队列这种

3.3.1线程池几大参数
3.3.1队列

无界队列oom

3.4锁

同步块大家都比较熟悉,通过 synchronized 关键字来实现;所有加上 synchronized 的方法和块语句,在多线程访问的时候,同一时刻只能有一个线程能够访问。

ConcurrentHashMap的锁

jdk1.8 使用到了 CAS+Volatile

synchronized+volatile(1.8版本)

CAS+Volatile

心想,确实是可以实现的呀!因为 AbstractQueuedSynchronizer(简称 AQS)内部就是通过 CAS + volatile(修饰同步标志位state) 实现的同步代码块。

volatile 保证了可见性和有序性,

cas 保证了原子性,像i++是三个操作,普通的保证不了这三个操作一起执行,然后使用cas 保证原子性。优点是可以保障原子性,但是缺点是有时候自旋时间太长,也会有问题。

AQS

AQS定义了一套多线程访问共享资源的同步器框架,许多同步类实现都依赖于它,如常用的ReentrantLock。 简单来说,AQS定义了一套框架,来实现同步类

AQS的核心思想是对于共享资源,维护一个双端队列来管理线程,队列中的线程依次获取资源,获取不到的线程进入队列等待,直到资源释放,队列中的线程依次获取资源。 AQS的基本框架如图所示:

AQS定义了一个实现同步类的框架,实现方法主要有tryAquiretryRelease,表示独占模式的资源获取和释放,tryAquireSharedtryReleaseShared表示共享模式的资源获取和释放。 源码分析如上文所述。

ReenTrankLock 锁
synchronized 锁对象头
Mysql的锁

表锁 行锁

CAS加volitale实现同步代码块,然后应用有 AQS ,

3.5 多线程 生产者与消费者

生产者 - 消费者模型 Producer-consumer problem 是一个非常经典的多线程并发协作的模型,在分布式系统里非常常见。

public void run() {synchronized (queue) {while (queue.size() == maxCapacity) { //一定要用 while,而不是 if,下文解释try {System.out.println("生产者" + Thread.currentThread().getName() + "等待中... Queue 已达到最大容量,无法生产");wait();System.out.println("生产者" + Thread.currentThread().getName() + "退出等待");} catch (InterruptedException e) {e.printStackTrace();}}if (queue.size() == 0) { //队列里的产品从无到有,需要通知在等待的消费者queue.notifyAll();}Random random = new Random();Integer i = random.nextInt();queue.offer(new Product("产品"  + i.toString()));System.out.println("生产者" + Thread.currentThread().getName() + "生产了产品:" + i.toString());}}作者:小齐本齐
链接:https://juejin.cn/post/6872131047032553486
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

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

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

相关文章

HQL,SQL刷题,尚硅谷

目录 相关表数据&#xff1a; 题目及思路解析&#xff1a; 查询结果排序&分组指定条件 1、查询学生的总成绩并按照总成绩降序排序 2、按照如下格式显示学生的语文、数学、英语三科成绩&#xff0c;没有成绩的输出为0&#xff0c;按照学生的有效平均成绩降序显示 3、查询一…

常用SQL查询方法与实例

目录 SELECT查询 INSERT查询 UPDATE查询 DELETE查询 JOIN查询 GROUP BY查询 HAVING查询 窗口函数 公共表表达式&#xff08;CTEs&#xff09; 递归查询 透视表 分析函数 解透视 条件聚合 日期函数 合并语句 情况语句 常用SQL查询方法有以下几种&#xff1a; S…

【无监督学习之聚类】

曾梦想执剑走天涯&#xff0c;我是程序猿【AK】 目录 简述概要知识图谱1. K-Means聚类2. 层次聚类&#xff08;Hierarchical Clustering&#xff09;3. DBSCAN&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;4. 谱聚类&#xff08;Spect…

一个实时波形图的封装demo(QT)(qcustomplot)

前言&#xff1a; 封装的一个实时波形图的类&#xff0c;可以直接提升使用。 提供了接口&#xff0c;可以更改颜色&#xff0c;样式&#xff0c;等等 参考&#xff1a; Qt Plotting Widget QCustomPlot - Introduction 另外参考了一个大神的作品&#xff0c;链接没找到。 项目…

#13Maven打包生成MD5校验文件的两种方式

目录 1、checksum-maven-plugin 2、maven-antrun-plugin 1、checksum-maven-plugin <plugin><groupId>net.ju-n.maven.plugins</groupId><artifactId>checksum-maven-plugin</artifactId><version>1.2</version><executions&g…

线路覆冰加重导线舞动风险,输电线路导线舞动在线监测装置保障运行安全

2月21日&#xff0c;山东烟台迎来强降雪天气&#xff0c;国网烟台供电公司紧急部署&#xff0c;组织运维人员联合智能巡检设备对重要变电站和输电线路进行巡视&#xff0c;确保电网安全稳定运行。 “雨雪天气给输电线路造成一定的影响&#xff0c;尤其是雨雪加上冰冻&#xff0…

NIST正式发布网络安全框架 2.0最终版:相比之前两个版本的六大重大变化

2月26日美国国家标准与技术研究院 (NIST) 正式发布了更新后的网络安全框架 (CSF)&#xff0c;这是其降低网络安全风险的里程碑式指导文件。新的 2.0 版本专为所有行业部门和组织类型而设计&#xff0c;从最小的学校和非营利组织到最大的机构和公司&#xff0c;无论其网络安全的…

Nodejs+vue汽车保养美容管理系统vscode前后端分离项目

汽车美容保养管理系统后台采用nodejs语言开发,前台页面和后台管理页面使用vue等技术开发,使用MySql作为数据持久化存储工具对汽车美容保养管理系统的用户等角色权限对应的功能等进行存储。采用vsocde集成IDE对汽车美容保养管理系统统进行开发,整合系统的各个模块。 拟开发的汽车…

[回归指标]R2、PCC(Pearson’s r )

R2相关系数 R2相关系数很熟悉了&#xff0c;就不具体解释了。 皮尔逊相关系数&#xff08;PCC&#xff09; 皮尔逊相关系数是研究变量之间线性相关程度的量&#xff0c;R方和PCC是不同的指标。R方衡量x和y的接近程度&#xff0c;PCC衡量的是x和y的变化趋势是否相同。R方是不…

Mac OS 制作可引导安装器并重新安装系统

Mac 使用 U盘或移动固态硬盘制作可引导的安装器&#xff08;以 Monterey 为例&#xff09; 本教程参考 Apple 官网相关教程 创建可引导 Mac OS 安装器 重新安装 Mac OS 相关名词解释 磁盘分区会将其划分为多个单独的部分&#xff0c;称为分区。分区也称为容器&#xff0c;不同…

Windows PowerShell 命令行历史记录补全

Windows 命令行历史记录补全 使用 powershell 安装PSReadLine 2.1.0 Install-Module PSReadLine -RequiredVersion 2.1.0检查是否存在配置文件 Test-path $profile # 为 false 则执行命令创建 New-item –type file –force $profile编辑配置文件 notepad $profile# 输入如下…

备战蓝桥杯---树形DP基础3

上一次我们讲了二叉苹果树&#xff0c;现在我们加一点难度&#xff0c;从二叉变成了多叉苹果树。 这样子我们就不可以直接按照上次的方法DP&#xff0c;我们其实可以发现&#xff0c;我们可以用类似背包的思想求解&#xff0c;这就是所谓的树上背包。 我们先加进第一个儿子来…

鸿蒙Harmony应用开发—ArkTS声明式开发(挂载卸载事件)

挂载卸载事件指组件从组件树上挂载、卸载时触发的事件。 说明&#xff1a; 从API Version 7开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 onAppear onAppear(event: () > void) 组件挂载显示时触发此回调。 卡片能力&#xff1a; …

go语言魔法技能go:linkname

我们在看Go语言的源码时&#xff0c;经常会看到一些特别的注释&#xff0c;比如&#xff1a; //go:build //go:linkname //go:nosplit //go:noescape //go:uintptrescapes //go:noinline //go:nowritebarrierrec等等&#xff0c;这些特别的注释其实是Go编译器的指示指令。这里…

VUE实现Office文档在线编辑,支持doc/docx、xls/xlsx、ppt/pptx、pdf等

1.微软提供的在线Office预览&#xff08;只能预览&#xff0c;不能编辑&#xff09; https://view.officeapps.live.com/op/view.aspx?src服务器上文档地址&#xff08;http开头&#xff09; 2.国内在线Office方案&#xff1a; 腾讯文档、石墨文档、飞书 优势&#xff1a;跨…

Linux红帽rhce认证多少钱?考个RHCE难不难?

Linux作为开源操作系统的佼佼者&#xff0c;已经广泛应用于各个领域。红帽认证工程师(Red Hat Certified Engineer&#xff0c;简称RHCE)作为Linux领域权威的认证之一&#xff0c;自然成为了众多IT从业者追求的目标。那么&#xff0c;RHCE认证的培训费用是多少?考取这一认证又…

Linux的条件变量

条件变量 条件变量本身不是锁&#xff0c;但是它可以造成线程阻塞。通常于互斥锁配合使用。给多线程提供一个会和的场合。 使用互斥量保护共享数据使用条件变量可以造成线程阻塞&#xff0c;等待某个条件的发生&#xff0c;当条件满足的时候解除阻塞。 条件变量的两个动作&a…

python 基础知识点(蓝桥杯python科目个人复习计划55)

今日复习内容&#xff1a;做题 例题1&#xff1a;体育健将 问题描述&#xff1a; 小蓝作为班级里的体育健将&#xff0c;他被安排在校运会时参加n个体育项目&#xff0c;第i个体育项目参赛需要耗时ai分钟&#xff0c;赛后休息需要bi分钟&#xff08;这意味着当他参加完这场比…

【AIGC大模型】InstantID 赏析

论文地址&#xff1a;https://arxiv.org/abs/2401.07519 InstantID 主页&#xff1a;https://instantid.github.io/ Demo &#xff1a;https://huggingface.co/spaces/InstantX/InstantID code&#xff1a; InstantID/InstantID: InstantID : Zero-shot Identity-Preserving…

计算机组成原理-第一/二章 概述和数据的表示和运算【期末复习|考研复习】

文章目录 前言第一章 计算机组成原理 概述及各种码1.1 计算机硬件的基本组成1.1.1 存储器1.1.2 运算器1.1.3 控制器 1.2 计算机的工作过程1.3 计算机的性能指标1.4 各个字长区别与联系 第二章 数据的表示与运算2.1 ASCII码2.2 各种码2.3 浮点数 总结 前言 给大家整理了一下计算…