多线程小知识

news2024/11/15 7:09:00

多线程

  • 多线程环境使用哈希表
    • HashMap
    • Hashtable
    • ConcurrentHashMap
  • 死锁
    • 死锁是什么
      • 两者之间的死锁
      • 多人之间的死锁
    • 死锁产生的四个必要条件:
      • 互斥使用
      • 不可抢占
      • 请求和保持
      • 循环等待
  • 不同的锁
    • ReentrantLock
    • Synchronized和ReentrantLock之间的区别:
    • 具体选择
    • Synchronized
    • 加锁工作过程
      • 偏向锁
      • 轻量级锁
      • 重量级锁
      • 锁消除
      • 锁粗化
  • 线程池
    • ThreadPoolExecutor构造方法
    • 执行流程
  • CAS && ABA
      • CAS
      • ABA

前几次给小小的给多线程做了一些小铺垫,现在我们就来稍微唠唠多线程中一些比较有意思的知识!

多线程环境使用哈希表

HashMap

原来我们学习的集合类,大部分都不是线程安全的,HashMap也不是线程安全的类,为此我们搞出了Hashtable以及ConcurrentHashMap

Hashtable

HashTable知识简单粗暴地给一些重要方法加上了锁,换言之,只要在多线程环境下使用了Hashtable,就会有阻塞的情况发生.
在这里插入图片描述
在这里插入图片描述

我们之间说过了只要是使用了synchronized,那么你写出来的代码大概率就和高效无缘了,之前我们写懒汉模式的时候,还要处处计较,我们当然可以无脑加锁,但是那样子就不专业了.
这边给put和get方法加锁,从效果上来看其实就是给Hashtable对象加锁了,我们使用的较多的方法就是这几个,所以一个Hashtable对象只有一把锁,锁冲突就会比较激烈,于是乎ConcurrentHashMap应运而生.

ConcurrentHashMap

我们要知道一个普通的哈希表的结构是,每个节点下面会挂着一串链表,每当我们想要插入或者是查询的时候,都要对数据进行哈希,找到对应链表的起始位置,然后慢慢遍历.
我们的ConcurrentHashMap并不是针对整个对象进行加锁,而是细化到了针对到了每个链表,只有当对同一个链表进行和写有关的操作的时候,才会发生锁竞争,这也就一定程度上提高了效率.

死锁

我们之前遇到到死循环和死递归,死锁就是把自己给锁死了.

死锁是什么

两者之间的死锁

我把车钥匙放在家里了,又把家里的钥匙放在了车里.
这样子是不是两者就僵住了啊.

多人之间的死锁

这里比较经典的问题就是哲学家就餐问题:
链接: 哲学家就餐
简单说一下,一座子的人都比较死板,吃饭都要先拿左手边的筷子,然后再拿右手边的筷子,同时这一桌子的人都比较绅士,如果右手边的筷子被占用,那么就要等到筷子不被占用为止,只有吃好了,他们才会放下筷子.
在这里插入图片描述

这样子如果极端情况下,这一桌子老哥同时拿起左手边的筷子,那么这一桌子的人这辈子都没办法吃完这一顿饭了.

死锁产生的四个必要条件:

互斥使用

即当资源被一个线程使用(占有)时,别的线程不能使用

不可抢占

资源请求者不能强制从资源占有者手中夺取资源,资源只能由资源占有者主动释放。

请求和保持

当资源请求者在请求其他的资源的同时保持对原有资源的占有。

循环等待

即存在一个等待队列:P1占有P2的资源,P2占有P3的资源,P3占有P1的资源。这样就形成了一个等待环路.
我们想要破局只要把上面任意一点突破了就行.
就比如哲学家就餐问题,我们只要稍加变通,给每根筷子编号,把拿起走左手边的改成拿起号码小的,这样子就可以了.

不同的锁

ReentrantLock

这把锁代表着可重入锁,比我们之前的synchronized多了几个方法:
lock(): 加锁, 如果获取不到锁就死等.
trylock(超时时间): 加锁, 如果获取不到锁, 等待一定的时间之后就放弃加锁.
unlock(): 解锁

Synchronized和ReentrantLock之间的区别:

synchronized 是一个关键字, 是 JVM 内部实现的(大概率是基于 C++ 实现). ReentrantLock 是标准库的一个类, 在 JVM 外实现的(基于 Java 实现).
synchronized 使用时不需要手动释放锁. ReentrantLock 使用时需要手动释放. 使用起来更灵活, 但是也容易遗漏 unlock.
synchronized 在申请锁失败时, 会死等. ReentrantLock 可以通过 trylock 的方式等待一段时间就放弃.
synchronized 是非公平锁, ReentrantLock 默认是非公平锁. 可以通过构造方法传入一个 true 开启公平锁模式
更强大的唤醒机制. synchronized 是通过 Object 的 wait / notify 实现等待-唤醒. 每次唤醒的是一个随机等待的线程. ReentrantLock 搭配 Condition 类实现等待-唤醒, 可以更精确控制唤醒某个指定的线程.

具体选择

锁竞争不激烈的时候, 使用 synchronized, 效率更高, 自动释放更方便.
锁竞争激烈的时候, 使用 ReentrantLock, 搭配 trylock 更灵活控制加锁的行为, 而不是死等.
如果需要使用公平锁, 使用 ReentrantLock.

Synchronized

  1. 开始时是乐观锁, 如果锁冲突频繁, 就转换为悲观锁.
  2. 开始是轻量级锁实现, 如果锁被持有的时间较长, 就转换成重量级锁.
  3. 实现轻量级锁的时候大概率用到的自旋锁策略
  4. 是一种不公平锁
  5. 是一种可重入锁
  6. 不是读写锁

加锁工作过程

JVM 将 synchronized 锁分为 无锁、偏向锁、轻量级锁、重量级锁 状态。会根据情况,进行依次升级。

偏向锁

并不是真正加锁,只是在内部给了一个标志位,避免了部分开销

轻量级锁

轻量级锁大概率是通过自旋来实现的,竞争并不是很激烈,自选一会也就拿到了

重量级锁

竞争比较激烈了,自旋也不好使了,开销还大,那就老老实实挂起等待吧

锁消除

就比如在单线程环境下使用StringBuffer,本身单线程就没有多线程安全那一套,那么这里的synchronized那一套只会平白徒增消耗,我们就把它给优化掉了

锁粗化

这里的粗和细指的是锁的粒度,也就是加锁时间的长度,如果加锁粗,那么同一段代码下我们进行加锁的次数也就少了,这样子开销也就少了,我个人感觉就是如果一段代码需要加锁的地方比较多,那么我们可以使用锁粗化,避免频繁加锁销毁锁带来的开销.

线程池

线程是轻量级进程,轻量就体现在除了第一次调用线程,线程的创建调度销毁所需要的开销都远远小于进程,但是凡事都是相对的,我们的线程池所需要的开销又要小于线程,池这个概念我们并不陌生,之前我们讲的字符串常量池也是一种池.
所谓池就是一盘大杂烩,就线程池来讲,你创建好的线程都会放在线程池里面,即使后面你想要销毁线程也不会真正销毁,想要调度创建线程了,首先先去线程池里面看看,看看之前有没有创建过线程,这样子又减少了一部分开销,但是这样的存储方式必然会占用内存

ThreadPoolExecutor构造方法

在这里插入图片描述
把创建一个线程池想象成开个公司. 每个员工相当于一个线程.

  1. corePoolSize: 正式员工的数量. (正式员工, 一旦录用, 永不辞退)
  2. maximumPoolSize: 正式员工 + 临时工的数目. (临时工: 一段时间不干活, 就被辞退).
  3. keepAliveTime: 临时工允许的摸鱼时间.
  4. unit: keepaliveTime 的时间单位, 是秒, 分钟, 还是其他值.
  5. workQueue: 传递任务的阻塞队列
  6. threadFactory: 创建线程的工厂, 参与具体的创建线程工作.
  7. RejectedExecutionHandler: 拒绝策略, 如果任务量超出公司的负荷了接下来怎么处理.
    AbortPolicy(): 超过负荷, 直接抛出异常. 把球丢给程序猿,您自己来
    CallerRunsPolicy(): 调用者负责处理
    DiscardOldestPolicy(): 丢弃队列中最老的任务.
    DiscardPolicy(): 丢弃新来的任务.

执行流程

在这里插入图片描述

CAS && ABA

CAS

CAS:compare and swap
在这里插入图片描述
CAS也可以从某种程度上保证原子性的问题,因为CAS整个工作流程是一条指令:如果我们取到的内存的值和我们所期望的值一样,那么首先第二个参数和第三个参数就会交换,然后再把第二个参数写回到第一个参数里面.
实际上我们要保证CAS的原子性还要基于一部分的代码
在这里插入图片描述
只有当CAS返回为true的时候才会交换,但实际上由于多线程,不可能每一次我们我们拿到的值都和期待的一样,这样子我们就会持续进入循环,每次都会要再去获取一遍内存中的值,这样子不论如何最终我们都会执行到一次CAS

ABA

ABA问题其实也是走了一个极端,加入就在我们刚刚执行完一次CAS的同时,我们又有一个操作把本该结束循环的条件又给修改了,这样子这次CAS我们又会多执行一次,是不是听上去并没有什么的,那如果是转账呢?我们先转了10万给别人,然后同时我们又收到了十万块钱,循环的条件是money!=10万,显然我们还会执行第二次,这不就是天大的问题了吗?
如何解决ABA问题也不难,每次我们针对内存进行操作完成之后,再给版本号进行自增如果寄存器中的版本号小于内存中的版本号,那么这次操作就作废

好了今天的内容差不多就到这里了,我希望我能通过最简单的语言教会给你们基本内容.
百年大道,你我共勉!

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

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

相关文章

using namespace std 是什么意思——C++命名空间

目录 namespace命名空间局部域和全局域namespace展开命名空间指定命名空间 命名空间的嵌套不同文件中的同名命名空间 using namespace std 是什么意思 我们先看一段C代码&#xff1a; #include <stdio.h> #include <stdlib.h>int rand 0;int main() {printf(&quo…

6.2 统计量与抽样分布

学习目标&#xff1a; 我的理解: 统计量是从一个样本中计算得到的数值&#xff0c;用于描述样本的某种特征或性质。统计量可以用来推断总体的特征或性质&#xff0c;因为样本是总体的一部分。 通常&#xff0c;统计量是通过对样本中的数据进行计算得到的&#xff0c;例如平均…

3年轻人20万开店日营业额79.2元,年轻人开店还能赚到钱吗?

最近&#xff0c;河南郑州的蔡先生和2个朋友合伙开一家汉堡店&#xff0c;生意很惨淡&#xff0c;日营业额79.2元。 蔡先生表示&#xff0c;他们开店失败的最大原因就是没有做好前期准备工作&#xff0c;产品没有吸引人的特色&#xff0c;导致正式营业后吸引不到客户。 蔡先生用…

Python 实现海康机器人工业相机 MV-CU060-10GM 的实时显示视频流及拍照功能

一、背景介绍 1、最近项目中需要给客户对接海康机器人工业相机 MV-CU060-10GM&#xff1b; 2、客户要求通过部署的管理平台&#xff0c;可以在页面上实现如下功能&#xff1a; 1&#xff09;相机视频流开始预览&#xff1b; 2&#xff09;相机视频流停止预览&#xff1b; 3&am…

三月份跳槽了,历经阿里测开岗4轮面试,不出意外,被刷了...

大多数情况下&#xff0c;测试员的个人技能成长速度&#xff0c;远远大于公司规模或业务的成长速度。所以&#xff0c;跳槽成为了这个行业里最常见的一个词汇。 前几天&#xff0c;我看到有朋友留言说&#xff0c;他在面试阿里的测试开发工程师的时候&#xff0c;灵魂拷问三小…

NIO非阻塞式网络通信实例

一、概述 1、NIO有三大核心部分&#xff1a;Channel(通道)&#xff0c;Buufer(缓存区)&#xff0c;Selector(选择器) Buffer缓存区 缓冲区本质上是一块可以写入数据&#xff0c;然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象&#xff0c;并提供了 一组方法&am…

❤Linux文件、目录与磁盘格式总结❤

文章目录 Linux文件、目录与磁盘格式总结Linux文件权限chgrpchmodchown文件种类Linux文件扩展名 Linux文件与目录管理常用的目录解释目录树绝对路径与相对路径cd(切换目录)pwd(显示当前目录)mkdir(建立一个新目录)rmdir(删除空目录)执行文件路径变量$PATHls(文件与目录的查看)c…

青藤首提“业安融合”理念,正式发布先进云安全方案CNAPP

4月18日&#xff0c;以“云时代&#xff0c;安全变了”为主题的2023年云安全高峰论坛在北京举行。会上&#xff0c;青藤首次提出“业安融合”理念&#xff0c;正式发布先进云安全方案CNAPP。 中国全面进入云和数字化时代 当前&#xff0c;全球已进入数字经济时代&#xff0c;…

物联感知产品如何助力企业实现智能化转型?

如果您的企业想要实现设备全生命周期管理、设备信息管理、设备监控和数据处理等功能&#xff0c;想要进行智能化数字转型&#xff0c;不妨了解一下物联感知。 物联感知产品是利用物联网技术&#xff0c;实现对物理世界的感知、联接和智能化。物联感知产品一般由四个部分组成&a…

python中的pyc文件了解一下?

基本说明 pyc 文件是 Python 编译过的字节码文件。当你运行一个 Python 程序时&#xff0c;Python 解释器首先将源代码&#xff08;通常是 .py 文件&#xff09;编译成字节码。这个字节码是一种低级的、与平台无关的代码&#xff0c;它可以被 Python 虚拟机&#xff08;Python…

TCP的连接管理机制(三次握手与四次挥手)

目录为啥要三次握手与四次挥手三次握手syn 与 ack三次握手具体流程四次挥手注意为啥要三次握手与四次挥手 相比于UDP, TCP是有连接的, 这个连接就体现在这了. 三次握手就是TCP建立连接, 四次挥手就是TCP断开连接. 三次握手 握手是指通信双方进行网络交互. 三次握手就相当于…

记录上传文件异常 /tmp/tomcat... (No space left on device)

一&#xff0c;问题描述 用postman调用上传接口&#xff0c;基本每两次调用会有一次报错&#xff0c;如下 {"timestamp": "2023-04-11T03:00:15.4690000","status": 500,"error": "Internal Server Error","exceptio…

【活动】想对大学的自己说……

写在前面&#xff1a; 时间过得真的很快&#xff0c;眨眼间我们已经走过了这么多年的大学时光。回想起来&#xff0c;我们曾经有过无数的欢笑和泪水&#xff0c;有过无数的成功和挫败&#xff0c;但是这些经历都让我们变得更加坚强和成熟。如果现在有机会回到大学时光&#xff…

【LInux】进程间通信 -- 匿名管道

前言 我们在学习进程管理&#xff0c;进程替换时&#xff0c;都强调了进程的独立性&#xff0c;那进程间通信是什么&#xff1f;这好像和进程的独立性相矛盾吧&#xff1f; 那么今天&#xff0c;我们就来学习进程间通信&#xff0c;和第一种通信方式 – 管道 文章目录 前言一. …

高效管理 Linux 进程:如何后台执行程序、查看进程、终止任务

目录 前言一、nohup命令详解1-1、nohup命令介绍1-2、语法格式1-2-1、基础语法介绍1-2-2、执行脚本文件1-2-3、执行python文件1-2-4、拓展延申&#xff1a;在服务器上运行后台进程1-2-5、nohup和&的区别 二、进程查看2-1、jobs命令&#xff08;基本不用&#xff09;2-2、ps命…

Android进阶宝典—在Compose中跳转Fragment

使用场景 我们原有的项目中基本采用的是单Activity架构&#xff0c;页面之间的跳转都是通过Navigation进行的&#xff0c;举个简单的例子。 在这种单Activity架构模式下&#xff0c;有一天我们想把MainActivity或者BFragment使用Compose重构&#xff0c;这个时候我们就需要去…

PasteSpider软件优势介绍

PasteSpider采用.netcore编写&#xff0c;运行于linux服务器的docker/podman里面&#xff0c;涉及的技术或者工具有podman/docker,registry,nginx,top,ssh,git,svn等。 PasteSpider可以更好的为你执行服务的升级和维护工作。支持集群模式安装&#xff0c;也支持单例模式运行。…

如何为 Apple 官方 SwiftUI 示例中的图表元素加上首显动画?

0. 概览 在 Apple 官方教程示例 Animating Views and Transitions 中,苹果为我们展示了如何为 SwiftUI 中的各种视图添加动画和过渡效果。 在示例的最后,我们在完成 3 种不同数据类型(Elevation, Heart Rate, Pace)切换的同时,顺面收获了美美的图表元素动画效果: 不过,…

科研方向与个人思考

文章目录 关于科研选题与方法的若干思考如何选题选题tips确定研究问题之后如何读论文——与一篇优秀论文作者的博弈阅读论文的技巧代码实现过程中成果发表四步走&#xff1a;科技论文的书写顺序学会利用工具科研的正确姿势 研究生时间线个人思考入门一个领域的步骤&#xff08;…

【有功-无功协调优化】基于改进多目标粒子群优化算法(小生境粒子群算法)的配电网有功-无功协调优化研究(Matlab代码实现)

&#x1f4a5; &#x1f4a5; &#x1f49e; &#x1f49e; 欢迎来到本博客 ❤️ ❤️ &#x1f4a5; &#x1f4a5; &#x1f3c6; 博主优势&#xff1a; &#x1f31e; &#x1f31e; &#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 …