Java面试之多线程安全(四)

server/2024/12/16 15:55:28/

此篇接上一篇Java面试之多线程状态(三)

对于线程安全问题,想从是什么、为什么、怎么做三个方面来整理这篇知识点。

首先,在《Java并发编程实战》书中,Brian Goetz大神是这样定义什么是线程安全性的。

当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。

简单来说,在多个线程访问某个方法或者对象的时候,不管通过任何的方式调用以及现场如何去交替执行。在程序中不做任何同步干预操作的情况下,这个方法或者对象的执行或修改都能按照预期的结果来反馈,那么这个类就是线程安全的。

实际上,线程安全问题的具体表现体现在三个方面,原子性,可见性,有序性

原子性,是指当一个线程执行一系列程序指令操作的时候,它应该是不可中断的,因为一旦出现中断,站在多线程的视角来看,这一系列的程序指令会出现前后执行结果不一致的问题。

这个和数据库里面的原子性是一样的,简单来说就是一段程序只能由一个线程完整的执行完成,而不能存在多个线程干扰。

CPU的上下文切换,是导致原子性问题的核心,而JVM里面提供了synchronized关键字来解决原子性问题。

CPU的上下文切换

可见性,就是说在多线程环境下,由于读和写是发生在不同的线程里面,有可能出现某个线程对共享变量的修改,对其他线程不是实时可见的。

导致可见性问题的原因有很多,比如CPU的高速缓存、指令重排序,编译器的指令重排序。

有序性,指的是程序编写的指令顺序和最终CPU运行的指令顺序可能出现不一致的现象。这种现象也可以称为指令重排序,

所以有序性也会导致可见性问题。可见性和有序性可以通过JVM里面提供的一个volatile关键字来解决。

线程安全问题只在多线程环境下才出现,单线程串行执行不存在此问题。保证高并发场景下的线程安全,可以从以下四个维度考量:

1.数据单线程内可见。单线程总是安全的。通过限制数据仅在单线程内可见,可以避免数据被其他线程篡改。最典型的就是ThreadLocal线程局部变量,它存储在独立虚拟机栈的局部变量表中,与其他线程毫无瓜葛。

2.只对对象。只读对象总是安全的。它的特性是允许复制、拒绝写入。最典型的只读对象有String、Integer等。一个对象想要拒绝任何写入,必须要满足以下条件:使用final关键字修饰,避免被继承;使用private final关键字避免属性被中途修改;没有任何更新方法;返回值不能为可变对象。

3.线程安全类。某些线程安全类的内部有非常明确的线程安全机制。比如StringBuffer就是一个线程安全类,它采用synchronized关键字来修饰相关方法。

4.同步与锁机制。如果想要对某个对象进行并发更新操作,但又不属于上述三类,需要自己在代码中实现安全的同步机制。虽然这个机制支持的并发场景很有价值,但非常复杂且容易出现问题。

注:此篇知识整理自《Java并发编程实战》、《咕泡》、《Java并发编程之美》



喜欢的朋友记得点赞、收藏、关注哦!!!


http://www.ppmy.cn/server/150669.html

相关文章

若依-帝可得app后端

视频地址 https://www.bilibili.com/video/BV1pf421B71v?t=510.1 APP后端技术栈 架构解析 验证码功能 开发环境使用改的是固定的验证码 12345正式环境使用的是 阿里云的短信方案@Override public void sendSms(String mobile) {// String code = RandomUtil.randomNumbers(5);…

相位小数偏差(UPD)估计基本原理

PPP中的一个关键性难题在于非差模糊度固定,成功固定非差模糊度可以使 PPP 的收敛速度和定位精度得到显著提升 。 相位小数偏差 (UPD) 是致使相位模糊度失去整数特性的主要因素,精确估计并校正 UPD 是实现非差模糊度固定的重要前提,也是实现…

【深度学习】 零基础介绍卷积神经网络(CNN)

零基础介绍 卷积神经网络(CNN,Convolutional Neural Network)是深度学习中的一种神经网络,特别擅长处理图像和视频等有空间结构的数据。 假设我们在做一个“照片分类”的任务,比如判断一张照片中是猫还是狗。下面用一…

【读书】试说中台之一

个人思考系列,开放题目,供后续复盘 起源 2015年12月7日,阿里巴巴全面启动中台战略,开启“大中台,小前台”时代。由此开始,中台的概念迅速火遍全网,成为一时新宠,各个企业都开始建立…

轻量级日志管理平台:Grafana Loki搭建及应用(详细篇)

前言 Grafana Loki是Grafana Lab团队提供的一个水平可扩展、高可用性、多租户的日志聚合系统,与其他日志系统不同的是,Loki最初设计的理念是为了为日志建立标签索引,而非将原日志内容进行索引。 现在目前成熟的方案基本上都是:L…

数据结构与算法

数据结构与算法复习 最近期末周准备考试&#xff0c;停更一段时间&#xff0c;结束之后继续更新图 图连通问题 ** 问题描述&#xff1a;**ConnectedComponents 给定无向图&#xff0c;计算无线图的连通分量 public class ConnectedComponents {private static Map<Verte…

uni-app多环境配置动态修改

前言 这篇文章主要介绍uniapp在Hbuilderx 中&#xff0c;通过工程化&#xff0c;区分不同环境、动态修改小程序appid以及自定义条件编译&#xff0c;解决代码发布和运行时手动切换问题。 背景 当我们使用uniapp开发同一个项目发布不同的环境二级路径不同时&#xff0c;这时候…

OpenCV图片添加水印

函数效果图&#xff1a; 本来只有蓝色背景&#xff0c;这两个人物是水印添加上去的 原理&#xff1a; 本实验中添加水印的概念其实可以理解为将一张图片中的某个物体或者图案提取出来&#xff0c;然后叠加到另一张图片上。具体的操作思想是通过将原始图片转换成灰度图&#x…