首页 > 其他分享 >如何回答线程安全

如何回答线程安全

时间:2023-10-03 17:23:01浏览次数:52  
标签:面试官 Java 对象 回答 安全 线程 多线程

前言

在面试过程中,很多的面试官都喜欢开局先来一个说一下你对线程安全的认识。这个问题呢广度挺大的,不同人理解不同,回答不同。如果不能好好的接下这一招,那么面试官就可能对你们后面的期待大大减小。

秋招在即,根据个人的见解和所查资料,对这一招进行拆招。(不一定是好招,仅为个人总结)

概念

首先呢,肯定要快速介绍一下线程安全。所谓的线程安全,就是在当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那么就称这个对象是线程安全的。

简单来说,就是在多线程下执行某个类,该对象始终都能保持正确的行为。

Java中的线程安全

在这里呢,如果有时间(面试官没打断)就跟可以面试官聊聊在Java中线程安全的安全划分层次。如果面试官直接问你那怎么保证线程安全呢,那就直接跳到下一个问题的答案。

在Java中根据线程的“安全强度”可以由强至弱来排序分别分为五类:不可变、绝对线程安全、相对线程安全、线程兼容和线程独立。(该部分摘录自参考资料书籍)

不可变

我们说过所谓线程安全在就是在多线程下执行,还能够始终保持正确的行为。而我们的不可变的对象一定是线程安全的,无论是对象的方法实现还是方法的调用者,都不需要再进行任何线程安全保障措施。

这个不可变其实很好理解,一旦我们的一个不可变对象被正确被构建出来(即没有发生this引用逃逸的情况),那其外部的可见性永远都不会改变的,永远都不会看到它在多个线程之中处于不一致的状态。

Java中,如果是多线程共享变量是一个基本数据类型可以使用final关键字来修饰,就可以保证不可变。如果共享数据是一个对象的话,只能让对象自己保证其行为不会其状态产生任何影响才行。比如String,用户调用substring(),replace()和concat()这些方法都不会影响它原来的值,只会返回一个新构造的字符串对象。保证对象行为不影响状态的途径有很多,一个比较有效的就是将带有状态变量的变量声明为final。(如Java中Integer类等)

绝对线程安全

绝对线程安全是比较严格的,它的定义是“不管运行时环境如何,调用者都不需要任何额外的同步措施。”例如我们的Vector就是一个线程安全容器,底层的方法也通过Synchronized来修饰,具备了原子性、可见性、有序性。但是它就不是一个绝对线程安全的,可以考虑这样一个特殊情况:

在多线程下,我们的一个线程恰好在错误的时间里面删除了一个元素,位置为i,那么另一个线程就有可能访问到这个i的时候发生数组越界异常。而我们的Vector要做到绝对的线程安全,就必须在它内部维护一组一致性的快照访问才行,每次对其中元素进行改动都要产生新的快照,但是时间和空间成本大。

相对线程安全

相对线程安全就是我们通常所说的线程安全,它保证对这个对象单次的操作是线程安全的,我们在调用的时候不需要进行额外的保证措施。在Java中,大部分声称线程安全的类都属于这种类型,例如Vector、HashTable、Collections的synchronizedCollection()方法包装的集合等。

线程兼容

线程兼容是指对象本身并不是线程安全的,但是可以通过在调用端正确地使用同步手段来保证对象在并发环境中可以安全地使用。我们平常说一个类不是线程安全的,通常就是指这种情况。Java类库API中大部分的类都是线程兼容的,如与前面的Vector和HashTable相对应的集合类ArrayList和HashMap等。

线程对立

线程对立是指不管调用端是否采取了同步措施,都无法在多线程环境中并发使用代码。

一个线程对立的例子是Thread类的suspend()和resume()方法。如果有两个线程同时持有一个线程对象,一个尝试去中断线程,一个尝试去恢复线程,在并发进行的情况下,无论调用时是否进行了同步,目标线程都存在死锁风险。

解决线程安全问题

线程安全也可以说是一类问题。因为只要我们用到多线程,就肯定需要考虑到线程安全的问题。所以我们针对线程安全问题有以下的方式去解决它。

线程安全实现方式

方式一:

核心思路是避免共享数据结构,共享状态。包括:

(1)使用线程local变量

(2)使用不可变对象

方式二:

核心思路是共享不可避免,需要通过条件来确保按照。包括:

(1)互斥锁(互斥同步)

(2)CAS原子操作(非阻塞同步)

Java中实现策略

(1)ThreadLocal变量,Volatile变量

(2)不可变对象有String,CopyOnWrite集合类

(3) 内置锁synchronized和Lock接口下是实现锁

(4) JUC下的原子类

参考资料

深入理解Java虚拟机第三版

如何理解什么是线程安全?

标签:面试官,Java,对象,回答,安全,线程,多线程
From: https://www.cnblogs.com/zhou111f/p/17741336.html

相关文章

  • java---多线程[(重点)上]
    15.1概念以前写的程序都是单线程,main方法程序称为主线程,主线程的结束所有的子线程都会跟着结束。多线程就代表着一个程序可以去做多件事情。线程:一个程序去做多件事情,每件事情由一个线程去完成。进程:一个进程由多个线程组成,一个进程至少有一个线程。一个进程就是一个应用程序多线......
  • 软件安全复习材料自用版本
    名词解释SQ:软件质量SQA:软件质量保证SA:软件保障SDS:软件定义安全VPN:虚拟专用网0day漏洞:已被发现但是官方还没有补丁的漏洞1day漏洞:官方发布补丁后大部分用户还未打补丁时的漏洞,仍然具有可利用性历史漏洞:距离补丁发布日期遥远且可利用性不高的漏洞CVSS:通用漏洞评分系统CVE:通用漏洞和......
  • java断点下载文件(整合多线程)
    技术介绍:断点下载指的是在文件下载过程中,如果下载中断或失败,比如下载到一半的时候停电了、断网了、不小心退出下载界面了等等,下一次进入下载页面可以从中断或失败的位置继续下载,而无需重新开始下载整个文件。 (注意:本文通过本地文件的拷贝来模拟文件传输的断点过程) 核心想法......
  • java本地文件多线程拷贝
    简单介绍:本地文件多线程拷贝是指通过多个线程同时进行文件复制操作。传统的文件复制操作往往是串行进行的,当需要复制单个大文件时,复制速度往往会比较慢。而采用多线程进行文件拷贝可以提高效率。通过同时创建多个线程,每个线程负责复制不同的文件或者不同的文件片段,可以充分利用计......
  • Golang goroutine 进程、线程、并发、并行
    goroutine 看一个需求需求:要求统计1-200000000000的数字中,哪些是素数?分析思路:1)传统的方法,就是使用一个循环,循环的判断各个数是不是素数(一个任务就分配给一个cpu去做,这样很不划算,而且非常慢)2)使用并发或者并行的方式,将统计素数的任务分配给多个goroutine去完成,这时就会使用到gor......
  • 什么是 security ReDoS 安全漏洞
    securityReDoS漏洞,全称"SecurityRegularExpressionDenialofService",是一种涉及到正则表达式的安全漏洞,可以导致严重的性能问题和拒绝服务攻击。正则表达式是一种用于匹配文本模式的强大工具,但如果不正确使用,可能会导致恶意输入数据引发的性能问题。在本文中,我将详细介绍secu......
  • redis7源码分析:redis 多线程模型解析
    多线程模式中,在main函数中会执行InitServerLastvoidInitServerLast(){bioInit();//关键一步,这里启动了多条线程,用于执行命令,redis起名为IO线程initThreadedIO();set_jemalloc_bg_thread(server.jemalloc_bg_thread);server.initial_memory_usage=......
  • 线程池
    ......
  • redis7源码分析:redis 单线程模型解析,一条get命令执行流程
    有了下文的梳理后redis启动流程再来解析redis在单线程模式下解析并处理客户端发来的命令1.当clientfd可读时,会回调readQueryFromClient函数voidreadQueryFromClient(connection*conn){client*c=connGetPrivateData(conn);intnread,big_arg=0;size_......
  • 如何获取 C#程序 内核态线程栈
    一:背景1.讲故事在这么多的案例分析中,往往会发现一些案例是卡死在线程的内核态栈上,但拿过来的dump都是用户态模式下,所以无法看到内核态栈,这就比较麻烦,需要让朋友通过其他方式生成一个蓝屏的dump,这里我们简单汇总下。二:如何生成内核态dump1.案例代码为了方便演示,来一段简单的......