常见面试题之线程中并发锁(二)

news2024/11/17 23:42:18

1. 什么是AQS

1.1. 概述

全称是AbstractQueuedSynchronizer,是阻塞式锁和相关的同步器工具的框架,它是构建锁或者其他同步组件的基础框架

AQSSynchronized的区别

synchronizedAQS
关键字,c++语言实现java语言实现
悲观锁,自动释放锁悲观锁,手动开启和关闭
锁竞争激烈都是重量级锁,性能差锁竞争激烈的情况下,提供了多种解决方案

AQS常见的实现类

  • ReentrantLock 阻塞式锁

  • Semaphore 信号量

  • CountDownLatch 倒计时锁

1.2. 工作机制

  • AQS中维护了一个使用了volatile修饰的state属性来表示资源的状态,0表示无锁,1表示有锁
  • 提供了基于FIFO的等待队列,类似于MonitorEntryList
  • 条件变量来实现等待、唤醒机制,支持多个条件变量,类似于MonitorWaitSet

在这里插入图片描述

  • 线程0来了以后,去尝试修改state属性,如果发现state属性是0,就修改state状态为1,表示线程0抢锁成功
  • 线程1和线程2也会先尝试修改state属性,发现state的值已经是1了,有其他线程持有锁,它们都会到FIFO队列中进行等待,
  • FIFO是一个双向队列,head属性表示头结点,tail表示尾结点

如果多个线程共同去抢这个资源是如何保证原子性的呢?

在这里插入图片描述

在去修改state状态的时候,使用的cas自旋锁来保证原子性,确保只能有一个线程修改成功,修改失败的线程将会进入FIFO队列中等待

AQS是公平锁吗,还是非公平锁?

  • 新的线程与队列中的线程共同来抢资源,是非公平锁

  • 新的线程到队列中等待,只让队列中的head线程获取锁,是公平锁

比较典型的AQS实现类ReentrantLock,它默认就是非公平锁,新的线程与队列中的线程共同来抢资源

2. ReentrantLock的实现原理

2.1. 概述

ReentrantLock翻译过来是可重入锁,相对于synchronized它具备以下特点:

  • 可中断

  • 可以设置超时时间

  • 可以设置公平锁

  • 支持多个条件变量

  • synchronized一样,都支持重入

在这里插入图片描述

2.2. 实现原理

ReentrantLock主要利用CAS+AQS队列来实现。它支持公平锁和非公平锁,两者的实现类似

构造方法接受一个可选的公平参数(默认非公平锁),当设置为true时,表示公平锁,否则为非公平锁。公平锁的效率往往没有非公平锁的效率高,在许多线程访问的情况下,公平锁表现出较低的吞吐量。

查看ReentrantLock源码中的构造方法:

在这里插入图片描述

提供了两个构造方法,不带参数的默认为非公平

如果使用带参数的构造函数,并且传的值为true,则是公平锁

其中NonfairSyncFairSync这两个类父类都是Sync

在这里插入图片描述

Sync的父类是AQS,所以可以得出ReentrantLock底层主要实现就是基于AQS来实现的

在这里插入图片描述

工作流程

在这里插入图片描述

  • 线程来抢锁后使用cas的方式修改state状态,修改状态成功为1,则让exclusiveOwnerThread属性指向当前线程,获取锁成功

  • 假如修改状态失败,则会进入双向队列中等待,head指向双向队列头部,tail指向双向队列尾部

  • exclusiveOwnerThreadnull的时候,则会唤醒在双向队列中等待的线程

  • 公平锁则体现在按照先后顺序获取锁,非公平体现在不在排队的线程也可以抢锁

3. synchronizedLock有什么区别 ?

参考回答

  • 语法层面
    • synchronized是关键字,源码在jvm中,用c++语言实现
    • Lock是接口,源码由jdk提供,用java语言实现
    • 使用synchronized时,退出同步代码块锁会自动释放,而使用Lock时,需要手动调用unlock方法释放锁
  • 功能层面
    • 二者均属于悲观锁、都具备基本的互斥、同步、锁重入功能
    • Lock提供了许多synchronized不具备的功能,例如获取等待状态、公平锁、可打断、可超时、多条件变量
    • Lock有适合不同场景的实现,如ReentrantLockReentrantReadWriteLock
  • 性能层面
    • 在没有竞争时,synchronized做了很多优化,如偏向锁、轻量级锁,性能不赖
    • 在竞争激烈时,Lock的实现通常会提供更好的性能

4. 死锁产生的条件是什么?

死锁:一个线程需要同时获取多把锁,这时就容易发生死锁

例如:

t1线程获得A对象锁,接下来想获取B对象的锁

t2 线程获得B对象锁,接下来想获取A对象的锁

代码如下:

package com.dcxuexi.basic;

import static java.lang.Thread.sleep;

public class Deadlock {

    public static void main(String[] args) {
        Object A = new Object();
        Object B = new Object();
        Thread t1 = new Thread(() -> {
            synchronized (A) {
                System.out.println("lock A");
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (B) {
                    System.out.println("lock B");
                    System.out.println("操作...");
                }
            }
        }, "t1");

        Thread t2 = new Thread(() -> {
            synchronized (B) {
                System.out.println("lock B");
                try {
                    sleep(500);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (A) {
                    System.out.println("lock A");
                    System.out.println("操作...");
                }
            }
        }, "t2");
        t1.start();
        t2.start();
    }
}

控制台输出结果

在这里插入图片描述

此时程序并没有结束,这种现象就是死锁现象…线程t1持有A的锁等待获取B锁,线程t2持有B的锁等待获取A的锁。

5. 如何进行死锁诊断?

当程序出现了死锁现象,我们可以使用jdk自带的工具:jpsjstack

步骤如下:

第一:查看运行的线程

在这里插入图片描述

第二:使用jstack查看线程运行的情况,下图是截图的关键信息

运行命令:jstack -l 46032

在这里插入图片描述

其他解决工具,可视化工具

  • jconsole

用于对jvm的内存,线程,类 的监控,是一个基于jmxGUI性能监控工具

打开方式:java安装目录bin目录下 直接启动jconsole.exe就行

  • VisualVM:故障处理工具

能够监控线程,内存情况,查看方法的CPU时间和内存中的对 象,已被GC的对象,反向查看分配的堆栈

打开方式:java安装目录bin目录下 直接启动jvisualvm.exe就行

6. ConcurrentHashMap

ConcurrentHashMap是一种线程安全的高效Map集合

底层数据结构:

  • JDK1.7底层采用分段的数组+链表实现

  • JDK1.8采用的数据结构跟HashMap1.8的结构一样,数组+链表/红黑二叉树。

6.1. JDK1.7concurrentHashMap

数据结构

在这里插入图片描述

  • 提供了一个segment数组,在初始化ConcurrentHashMap的时候可以指定数组的长度,默认是16,一旦初始化之后中间不可扩容
  • 在每个segment中都可以挂一个HashEntry数组,数组里面可以存储具体的元素,HashEntry数组是可以扩容的
  • HashEntry存储的数组中存储的元素,如果发生冲突,则可以挂单向链表

存储流程

在这里插入图片描述

  • 先去计算keyhash值,然后确定segment数组下标
  • 再通过hash值确定hashEntry数组中的下标存储数据
  • 在进行操作数据的之前,会先判断当前segment对应下标位置是否有线程进行操作,为了线程安全使用的是ReentrantLock进行加锁,如果获取锁是被会使用cas自旋锁进行尝试

6.2. JDK1.8concurrentHashMap

JDK1.8中,放弃了Segment臃肿的设计,数据结构跟HashMap的数据结构是一样的:数组+红黑树+链表

采用CAS + Synchronized来保证并发安全进行实现

  • CAS控制数组节点的添加

  • synchronized只锁定当前链表或红黑二叉树的首节点,只要hash不冲突,就不会产生并发的问题 , 效率得到提升

在这里插入图片描述

7. 导致并发程序出现问题的根本原因是什么?

Java并发编程三大特性

  • 原子性

  • 可见性

  • 有序性

(1)原子性

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

比如,如下代码能保证原子性吗?

在这里插入图片描述

以上代码会出现超卖或者是一张票卖给同一个人,执行并不是原子性的

解决方案:

1.synchronized:同步加锁

2.JUC里面的lock:加锁

在这里插入图片描述

(2)内存可见性

内存可见性:让一个线程对共享变量的修改对另一个线程可见

比如,以下代码不能保证内存可见性

在这里插入图片描述

解决方案:

  • synchronized

  • volatile(推荐)

  • LOCK

(3)有序性

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

还是之前的例子,如下代码:

在这里插入图片描述

解决方案:

  • volatile

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

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

相关文章

CISSP证书考试难度大吗?本文教你如何轻松拿下CISSP

主题:CISSP含金量、CISSP考试经验、CISSP备考、CISSP考试大纲 CISSP含金量高 CISSP注册信息系统安全师认证是信息安全领域被全球广泛认可的IT安全认证,一直以来被誉为业界的“金牌标准”。CISSP认证不仅是对个人信息安全专业知识的客观评估&#xff0c…

给若依添加单元测试(一)

给若依添加单元测试 方案二(异常困难但企业开发一般用这个) 方案一(简单) 在 admin 模块中添加单元测试 S1.在 src 目录下创建 test.java.MapperTests 文件 S2.将以下内容复制进去 import com.ruoyi.RuoYiApplication; imp…

初学mybatis(六)动态sql

学习回顾:初学mybatis(五) 一、动态SQL 介绍 什么是动态SQL:动态SQL指的是根据不同的查询条件 , 生成不同的Sql语句. 官网描述: MyBatis 的强大特性之一便是它的动态 SQL。如果你有使用 JDBC 或其它类似框架的经验&…

小研究 - Java 指针分析综述(三)

近年来静态程序分析已成为保障软件可靠性、安全性和高效性的关键技术之一. 指针分析作为基 础程序分析技术为静态程序分析提供关于程序的一系列基础信息,例如程序任意变量的指向关系、变量 间的别名关系、程序调用图、堆对象的可达性等. 介绍了 Java 指针分析的重要…

微信小程序:实名认证登录 [2018年]

1、[微信开发社区]微信支付实名信息小程序授权接口能力(用户获取用户真实姓名,身份证号码) 微信开放社区 2、注意事项 四、接口文档 略。

English Learning - L3 纠音 W8 Lesson7 Ted Living Beyond Limits 2023.06.27 周二

朗读内容: Lesson 7 Day 47 - 51 句子 Ted Living Beyond Limits 3-22

GPT-4 参加2023年高考数学,人工智能对话机器人和人类对决,快谁速度快

ChatGPT从入门到精通,一站式掌握办公自动化/爬虫/数据分析和可视化图表制作 全面AI时代就在转角 道路已经铺好了 “局外人”or“先行者” 就在此刻 等你决定 让ChatGPT帮你高效实现职场办公!行动起来吧。 【点击查看更多知识】ChatGPT从入门到精通&am…

springboot中Thymeleaf模板插入Freemarker模板页面

概述 最近在修改springboot架构的项目,项目之前配置的是Thymeleaf模板, 但是在我新加的功能中,我非常想用Freemarker模板来新加一些页面功能。 看到网上很多其他地方描述,要么用不同的文件后缀来区分(如html文件为Thymeleaf&…

【java 程序设计实训】学生请假管理系统

学生请假管理系统 运行结果学生请假管理系统需求分析GUI 编程事件处理数据库编程部分代码项目结构实体类 Admin.javaLeaveData.javaUserLogin.javaMainWindow.javaTeacherReviewFrame.javaleaveList.java 注:完整内容可下载查看完整报告 运行结果 学生请假管理系统需…

mac配置VScode主题加makefile etc

profile配置: 参考链接:https://www.bilibili.com/video/BV1YW4y1M7uX/?spm_id_from333.999.0.0&vd_sourced75fca5b05d8be06d13cfffd2f4f7ab5 https://code.visualstudio.com/docs/cpp/config-clang-mac vscode profiles如下: {//…

蓝桥杯专题-试题版-【九宫重排】【格子刷油漆】【回文数字】【国王的烦恼】

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 👉关于作者 专注于Android/Unity和各种游…

空间曲线的切线和法平面与曲面的切平面和法线

(一)空间曲线的切线和法平面 1. 参数方程的形式 理解和记住如下逻辑: 该两个公式,笔者可以理解但是无法证明。 2. 参数方程外的第二种形式: 此种变换的本质,就是将多元函数转换为参数方程的形式。如此看…

English Learning - L3 作业打卡 Lesson7 Day54 2023.6.29 周四

English Learning - L3 作业打卡 Lesson7 Day54 2023.6.29 周四 引言🍉句1: I daydreamed like I did as a little girl and I imagined myself walking gracefully, helping other people through my journey and snowboarding again.成分划分连读爆破语调 &#x…

Learn Mongodb 可是工具及基本命令的使用 ③

作者 : SYFStrive 博客首页 : HomePage 📜: PHP MYSQL 📌:个人社区(欢迎大佬们加入) 👉:社区链接🔗 📌:觉得文章不错可以点点关注 &#x1f44…

Spark 3.4.0新特性--UI支持存储在RocksDB中

背景 对于Spark来说,目前存储所有的事件信息以及UI所需要的信息都是默认存储在内存中,这在CS中,对于以Spark作为 Server的模式下,会导致OOM,也会导致造成之前作者提交PR:Multi sparkSession should share …

Java泛型详解:为什么使用泛型?如何使用泛型?

Java泛型详解:为什么使用泛型?如何使用泛型? 💘一、为什么使用泛型?💘二、如何使用泛型?💖1. 泛型类的使用:💖2. 泛型方法的使用:💖3.…

什么是ABP?

1、ABP背后的思想——DDD(领域驱动设计) ABP架构: ABP实现了多层架构(领域层,应用层,基础设施层和表示层),以及领域驱动设计(实体,存储库,领域服…

(R)-tert-Bu4-DOTAGA,817562-90-6,(R)-DOTAGA-四叔丁酯,的反应特点及性质研究

​ 规格单位:g |货期:按​照具体的库存进行提供 | 纯度:95% 试剂描述: (R)-tert-Bu4-DOTAGA大环化合物是一种多齿配体,其配位原子位于环的骨架上,大环的配位原子可以是O、N、S、Se、P、As等。有二维的…

C++primer(第五版)第七章(类)

类的基本思想是数据抽象和封装. 数据抽象是一种依赖于接口和实现的分离的编程技术. 封装实现了类的接口和实现的分离. 7.1定义抽象数据类型 定义一个抽象数据类型使用关键字struct或是clas(差别仅在于默认访问权限修饰符). //这是一个简单的类定义 class Student{ …

C++ 结合 opencv读取图片与视频

C 结合 opencv读取图片与视频 文章目录 C 结合 opencv读取图片与视频一、安装opencv二 、配置文件准备2.1 新建立文件夹2.2 .vscode文件下配置文件(1)配置tasks.json文件(1)配置launch.json 三 、src文件下代码编写3.1 图片的读取…