【Java面试丨并发编程】线程中并发安全

news2024/11/28 16:46:54

一、Synchronized关键字的底层原理

1. Synchronized的作用

  • Synchronized【对象锁】采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】,其他线程再想获取这个【对象锁】时就会阻塞住

2. Monitor

  • Synchronized【对象锁】底层是由Monitor实现,线程获得锁时需要使用对象(锁)关联的Monitor
    在这里插入图片描述
  • Monitor被翻译为监视器,由JVM提供,C++语言实现,在Monitor内部有三个属性,分别为Owner、EntryList、WaitSet
    在这里插入图片描述
    (1)Owner:存储当前获取锁的线程,有且只能存储一个线程
    (2)EntryList:存储没有抢到锁的线程,此处均为处于Blocked阻塞状态的线程
    (3)WaitSet:存储调用wait()方法的线程,此处均为Waiting等待状态的线程

3. 锁升级

  • Java中的Synchronized有偏向锁、轻量级锁、重量级锁三种形式,分别对应了锁只被一个线程持有、不同线程交替持有锁、多线程竞争锁三种情况
  • 在JDK 1.6引入了两种新型锁机制:偏向锁和轻量级锁,它们的引入是为了解决在没有多线程竞争或基本没有竞争的场景下,因使用传统锁机制带来的性能开销问题
    在这里插入图片描述
  • 总结:一旦锁发生了竞争,都会升级为重量级锁

二、谈谈JMM(Java内存模型)

  • Java内存模型(Java Memory Model,JMM):定义了共享内存中多线程程序读写操作的行为规范,通过这些规则来规范对内存的读写操作,从而保证指令的正确性
    在这里插入图片描述
  • 总结
    (1)JMM把内存分为两块,一块是私有线程的工作区域(工作内存),另一块是所有线程的共享区域(主内存)
    (2)线程跟线程之间是相互隔离的,线程跟线程之间交互需要通过主内存

三、CAS你知道吗

1. 介绍

  • CAS(Compare And Swap,比较再交换):体现了一种乐观锁的思想,在无锁的情况下,能够保证线程操作共享数据的原子性
  • 在JUC(java.util.concurrent)包下实现的很多类都用到了CAS操作
    (1)AbstractQueuedSynchronizer(AQS框架)
    (2)AtomicXXX类(原子类)
  • 在操作共享变量的时候使用的是自旋锁,效率上更高一些
  • CAS的底层是调用Unsafe类中的方法,都是操作系统提供的,其他语言实现

2. CAS数据交换流程

在这里插入图片描述

3. 自旋锁

  • 第一次CAS失败后,通过自旋操作,会重新加载主内存中共享变量V值到线程的工作内存中,将A值覆盖为新的V值,然后再去CAS操作,直到成功为止
  • 自旋锁:因为没有加锁,所以线程不会陷入阻塞状态,效率较高;但是如果线程之间竞争激烈,重试频繁发生,效率会受影响
    在这里插入图片描述

4. CAS底层实现

  • CAS底层依赖于一个Unsafe类来直接调用操作系统底层的CAS指令
    在这里插入图片描述
  • ReentrantLock中实现CAS的代码
    在这里插入图片描述

5. 乐观锁和悲观锁

  • 乐观锁
    (1)CAS基于乐观锁的思想,最乐观的估计,不怕别的线程来修改共享变量,就算改了也没关系,我吃点亏再重试
  • 悲观锁
    (1)Synchronized基于悲观锁的思想,最悲观的估计,得防着其他线程来修改共享变量,我上了锁,你们都别想改,我改完了解开锁,你们才有机会修改

四、什么是AQS

1. 介绍

  • AQS(AbstractQueuedSynchronizer,抽象队列同步器):是构建锁或者其他同步组件的基础框架
  • AQS和Synchronized的区别
    在这里插入图片描述
  • AQS常见的实现类
    (1)ReentrantLock:阻塞式锁
    (2)Semaphore:信号量
    (3)CountDownLatch:倒计时锁

2. AQS工作机制

  • AQS内部维护了一个先进先出的双向队列,队列中存储着排队的线程
  • AQS内部还有一个属性state,这个state就相当于一个资源,默认是0(无锁状态)。如果队列中有一个线程成功修改state为1,则当前线程就相当于获取了资源(锁)
  • 基本工作机制
    在这里插入图片描述
  • 多个线程共同去抢这个state资源,如何保证原子性
    在这里插入图片描述
  • AQS是公平锁,还是非公平锁
    在这里插入图片描述

五、ReentrantLock的实现原理

1. 特点

  • ReentrantLock为可重入锁,相对于Synchronized锁具备以下特点
    (1)可中断
    (2)可以设置超时时间
    (3)可以设置公平锁
    (4)支持多个变量
    (5)与Synchronized锁一样,都支持重入,调用lock()方法获取到锁之后,再次调用lock()方法是不会阻塞的

2. 实现原理

  • ReentrantLock主要利用CAS+AQS队列来实现的,支持公平锁和非公平锁

  • ReentrantLock的构造方法接收一个可选的公平参数(默认:非公平锁),当设置为true时,表示公平锁,否则为非公平锁
    在这里插入图片描述

  • 公平锁的效率往往没有非公平锁效率高,在多线程访问的情况下,公平锁表现出较低的吞吐量

  • 具体描述
    在这里插入图片描述

六、死锁产生的条件是什么

1. 介绍

  • 死锁:一个线程需要同时获取多把锁,这时候就容易发生死锁
    在这里插入图片描述

2. 如何进行死锁诊断

  • 当程序出现了死锁现象,可以使用JDK自带的工具:jps和jstack
    (1)jps:输出JVM中运行的进程状态信息
    (2)jstack:查看Java进程内线程的堆栈信息
    在这里插入图片描述
  • 其他工具查看
    (1)jconsole.exe
    在这里插入图片描述
    (2)VisualVM
    在这里插入图片描述

七、谈谈你对volatile的理解

1. 介绍

  • 一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义
    (1)保证线程之间的可见性
    (2)禁止进行指令重排

2. 保证线程之间的可见性

  • 用volatile修饰共享变量,能够防止编译器等优化发生,让一个线程对共享变量的修改对另一个线程可见
  • 可见性问题分析:主要是因为在JVM虚拟机中有一个JIT(即时编译器)给代码做了优化
    在这里插入图片描述
    (1)解决方案一:在程序运行的时候加入VM参数-Xint,表示禁用JIT即时编译器【不推荐,得不偿失,其他程序还要使用JIT】
    (2)解决方案二:在修饰共享变量的时候加上volatile,告诉JIT不要对volatile修饰的变量做优化

3. 禁止指令重排序

  • 用volatile修饰共享变量时,会在读、写共享变量时加入不同的屏障,阻止其他读写操作越过屏障,从而达到阻止重排序的效果
  • 指令重排序演示
    在这里插入图片描述
  • 解决指令重排序演示
    在这里插入图片描述
  • volatile使用技巧
    (1)写变量:让volatile修饰的变量在代码最后位置
    (2)读变量:让volatile修饰的变量在代码最开始位置

八、聊一下ConcurrentHashMap

1. 介绍

  • ConcurrentHashMap是一种线程安全的高效Map集合
  • 底层数据结构
    (1)JDK 1.7:采用分段的数组+链表实现
    (2)JDK 1.8:采用的数据结构和HashMap一样,数组+链表/红黑二叉树

2. 添加数据逻辑

  • JDK 1.7:ReentrantLock锁+CAS
    (1)整体流程
    在这里插入图片描述
    (2)添加数据
    在这里插入图片描述
  • JDK 1.8:Synchronized锁+CAS
    (1)CAS控制数组节点的添加
    (2)Synchronized只是锁定当前链表/红黑树二叉树的首节点,只要hash不冲突,就不会产生并发问题,效率得到提升
    (3)添加数据
    在这里插入图片描述

九、导致并发程序出现问题的根本原因是什么

1. 原子性

  • 一个线程在CPU中操作不可暂停,也不可中断,要不执行完成,要不不执行

2. 可见性

  • 一个线程对共享变量的修改对另一个线程可见

3. 有序性

  • 指令重排序:处理器为了提高程序运行效率,可能会对输入代码进行优化。它不保证程序中各个语句的执行先后顺序与代码中的顺序一致

4. 解决方案

  • 原子性:Synchronized、Lock
  • 可见性:volatile、Synchronized、Lock
  • 有序性:volatile

十、Synchronized锁和Lock锁有什么区别

1. 语法层面

  • Synchronized是Java关键字,源码在JVM中,由C++语言实现
  • Lock是接口,源码由JDK提供,Java语言实现
  • 使用Synchronized时,退出同步代码块,锁会自动释放
  • 使用Lock时,需要手动调用unlock()方法释放锁

2. 功能层面

  • 二者均属于悲观锁,都具备基本的互斥、同步、锁重入功能
  • Lock提供了许多Synchronized不具备的功能,比如:公平锁、可打断(lock.lockInterruptibly()方法&t1.interrupt()方法)、可超时(lock.tryLock(long time)方法)、多条件变量(lock.newCondition()方法&c1.await()方法&c1.signal()方法)
  • Lock有适合不同场景的实现,比如:ReentrantLock、ReentrantReadWriteLock(读写锁)

3. 性能层面

  • 在没有竞争时候,Synchronized做了很多优化,性能不赖,比如:偏向锁、轻量级锁
  • 在竞争激烈时候,Lock的实现通常会提供更好的性能

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

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

相关文章

泰裤辣!这是什么操作,自动埋点,还能传参?

目录 前言 参数放在注释中 准备入口文件 编写插件 运行代码 完整代码 参数放在局部作用域中 准备源代码 编写插件 运行代码 完整代码 总结 前言 在上篇文章讲了如何通过手写babel插件自动给函数埋点之后,就有同学问我,自动插入埋点的函数怎么…

基于IMX6ULL的AP3216C的QT动态数据曲线图显示

前言:本文为手把手教学 LinuxQT 的典型基础项目 AP3216C 的数据折线图显示,项目使用正点原子的 IMX6ULL 阿尔法( Cortex-A7 系列)开发板。项目需要实现 AP3216C 在 Linux 系统下的驱动,使用 QT 设计 AP3216C 的数据显示页面作为项目的应用层。…

消息中间件RabbitMQ简介

1.1消息队列中间件简介 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题实现高性能,高可用,可伸缩和最终一致性[架构] 使用较多的消息队列有ActiveMQ,RabbitMQ&#xff…

人工智能安全风险:零信任的作用

人工智能(AI)和机器学习技术飞速发展,我们所处的时代正在经历前所未有的创新。但是,技术飞速发展的同时也带来了各种挑战。人工智能技术越来越复杂,与之相关的网络安全风险也越来越棘手,随之产生了一个新的…

TortoiseGit 入门指南10:贮藏

有时,当你在项目的一部分上已经工作一段时间后,所有东西都进入了混乱的状态, 而这时你想要切换到另一个分支做一点别的事情。 问题是,你不想仅仅因为过会儿回到这一点而为做了一半的工作创建一次提交。 针对这个问题的答案是贮藏 …

【Linux指令集】---unzip指令(超详细)

个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【Linux专栏】🎈 本专栏旨在分享学习Linux的一点学习心得,欢迎大家在评论区讨论💌 演示环境&#xff1…

JVM系统优化实践(19):GC生产环境案例(二)

您好,这里是「码农镖局」CSDN博客,欢迎您来,欢迎您再来~ 接昨天的问题继续来说,在高并发场景中,对象过多容易导致OOM。由于高并发导致Young GC存活对象过多,因此会有太多对象进入老年代&#xf…

关于unity Content Size Fitter 套 Content Size Fitter

首先:最好不要unity Content Size Fitter 套 Content Size Fitter 这样最后得到的变化可能会错误 unity也提示了,父物体如果有了,那么子物体就不要再加了。 但是你们要的需求: 一级父物体 ➡自适应大小➡二级父物体&#xff08…

经典目标检测R-CNN系列(2)Fast R-CNN

经典目标检测R-CNN系列(2)Fast R-CNN Fast R-CNN是作者Ross Girshick继R-CNN后的又一力作。 同样使用VGG16作为网络的backbone,与R-CNN相比训练时间快9倍,测试推理时间快213倍,准确率从62%提升至66%(Pascal VOC数据集上)。 1 Fast R-CNN的…

Java List 与数组互转

前言 略 数组转 List 方法1 Employee[] array new Employee[]{emp1, emp2, emp3}; List<Employee> list Arrays.asList(array);Arrays.asList 返回的是固定长度的数组&#xff0c;扩大或缩小列表的操作将返回UnsupportedOperationException。 数组转 List 方法2 E…

【C++STL】“vector“容器的模拟实现

vector的模拟实现 模拟实现成员变量构造函数无参构造函数初始化n个val的构造函数迭代器区间构造函数 拷贝构造析构函数begin&#xff08;&#xff09;end&#xff08;&#xff09;swap&#xff08;&#xff09;reserve()resize()capacity()size()重载[]运算符重载赋值运算符ins…

自学网络安全(黑客)为什么火了?

网安专业从始至终都是需要学习的&#xff0c;大学是无法培养出合格的网安人才的。这就是为啥每年网安专业毕业生并不少&#xff0c;而真正从事网安岗位的人&#xff0c;寥寥无几的根本原因。 如果将来打算从事网安岗位&#xff0c;那么不断学习是你唯一的途径。 网络安全为什…

应对 618、双十一等大促期间的高负载,API 性能测试应该怎么做?负载测试、基线测试、冒烟测试、浸泡测试、峰值测试和尖峰测试详解

随着应用程序和服务交付速度的不断提高&#xff0c;在按时交付应用程序的竞赛中&#xff0c;性能测试往往会退居其次。但是&#xff0c;在节假日期间&#xff0c;购物额都会大幅增长。在这种一年中的成败时刻&#xff0c;公司是无法接受他们的应用程序在高负载下变得不可靠的。…

第四章 云原生架构之Kubernetes基础知识

1、K8S整体架构 1.1、概述 ​ Kubernetes是一个可移植、可扩展的开源平台&#xff0c;用于管理容器化的工作负载和服务&#xff0c;简称 K8S。K8S的本质是一组服务器集群&#xff0c;可以在对应服务器集群的每个节点上运行程序&#xff0c;来对节点中的容器进行管理。类似Mas…

Pytest+Jenkins+Allure的接口自动化测试

目录 生成Allure 两种形式 一 项目内直接生成不依赖Jenkins 1.先安装好allure 将allure\bin配置到环境变量中 cmd 命令行输入&#xff1a;allure 校验是否安装成功 2. 将json文件生成html文件 执行 allure generate report/ -o report/html其中的report/ 为生成的json路径&a…

OCPM和CPM有什么区别?

CPM和OCPM这两种收费模式的对比 Cpm&#xff1a;表示千次展示费用&#xff0c;是数据指标&#xff0c;也是一种出价方式。代表展现一千次的消费&#xff0c;也就是你展现1000次要给媒体多少钱 例如某企业广告曝光量是50万&#xff0c;总广告价格为10000元&#xff0c;那么千人…

matplotlib 笔记:marker 款式

1 ec 边缘颜色 marker 边缘的颜色 import numpy as np import matplotlib.pyplot as pltxnp.linspace(0,10) ynp.sin(x)1.5 plt.figure(figsize(10,10)) plt.scatter(x,y,ecC9) plt.show() 2 fc 填充颜色 face color 填充颜色 3 lw 边缘宽度 4 s 点的大小 5 marker 点款式 i…

设计模式 ~ 工厂模式

工厂模式 工厂模式是一种设计模式&#xff0c;指在通过使用工厂函数或构造函数来创建对象&#xff1b; 它提供了一种灵活的方式来创建对象实例&#xff0c;而无需直接调用构造函数或使用new关键字&#xff1b; 可以分类&#xff0c;解耦&#xff1b; 可以扩展多个类&#xff0…

Baidu——基于大模型的优质Prompt开发课-写代码

软件开发产业趋势与技术革新 大模型驱动的软件开发 代码辅助开发模型 实际操作 你是一名非常专业的产品经理&#xff0c;请问如果我要做一个图片字符画的工具的调研&#xff0c;需要哪些步骤 你是一名编程大牛&#xff0c;目前我想做一个图像字符画的工具&#xff0c;这个工具要…

前缀、中缀、后缀表达式及简易运算实现总结

title: 前缀、中缀、后缀表达式及简易运算实现总结 date: 2023-06-30 10:25:50 tags: 表达式 categories:开发知识及其他 cover: https://cover.png feature: false 1. 概念 1.1 什么是前缀、中缀、后缀表达式&#xff1f; 前缀表达式&#xff1a;又称波兰式&#xff08;Pol…