当前位置: 首页 > news >正文

.net core 线程锁,互斥锁,自旋锁,混合锁

线程锁、互斥锁、自旋锁和混合锁是多线程编程中的重要概念,它们用于控制对共享资源的访问,避免数据竞争和不一致性。每种锁有其特定的适用场景和特点。我们来逐一解释它们,并进行比较。

1. 线程锁(Thread Lock)

线程锁的概念泛指任何用于同步多线程访问共享资源的机制。它的目的是确保在同一时刻只有一个线程可以访问资源,从而避免多个线程并发访问时发生数据竞争(race condition)或资源不一致。

线程锁通常是通过以下几种锁机制来实现的:

  • 互斥锁(Mutex)
  • 自旋锁(SpinLock)
  • 读写锁(ReadWriteLock)
  • 信号量(Semaphore)
  • 临界区(CriticalSection)

不同类型的锁有不同的实现方式和适用场景。

2. 互斥锁(Mutex)

互斥锁(Mutex)是一种最常见的同步原语,用于控制对共享资源的访问。它的基本思想是:如果一个线程已经获得了锁,其他线程必须等待,直到锁被释放,才能继续执行。

特点
  • 线程阻塞:当一个线程尝试获取互斥锁时,如果锁已被其他线程持有,线程会被挂起,直到锁可用为止。
  • 适用于长时间持有锁的情况:如果临界区代码较长,或线程会执行大量计算时,使用互斥锁能有效避免 CPU 资源的浪费。
  • 系统开销较高:挂起和恢复线程的操作比自旋等待更消耗系统资源。
示例:C# 中的 lock(实际上是基于 Monitor 的实现)
class Program
{private static readonly object lockObj = new object();private static int counter = 0;static void Main(){Thread thread1 = new Thread(IncrementCounter);Thread thread2 = new Thread(IncrementCounter);thread1.Start();thread2.Start();thread1.Join();thread2.Join();Console.WriteLine("Final counter value: " + counter);}static void IncrementCounter(){lock (lockObj)  // 获取锁{counter++;  // 临界区Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} incremented counter to {counter}");}}
}

3. 自旋锁(SpinLock)

自旋锁是一种非常轻量级的同步机制,线程在尝试获取锁时,不会被挂起,而是会在一个循环中不断检查锁是否已经释放。线程会不断“自旋”并消耗 CPU 时间,直到获得锁。

特点
  • 忙等待:当一个线程请求自旋锁时,如果锁已经被其他线程持有,它会不断地检查锁是否已被释放,这种行为被称为“自旋”。
  • 适用于锁持有时间短的场景:当临界区代码执行时间非常短时,自旋锁可以避免线程挂起和恢复的高开销。
  • CPU 资源消耗较高:如果锁持有时间较长,多个线程可能会造成大量 CPU 资源的浪费。
示例:C# 中的 SpinLock
using System;
using System.Threading;class Program
{private static SpinLock spinLock = new SpinLock();private static int counter = 0;static void Main(){Thread thread1 = new Thread(IncrementCounter);Thread thread2 = new Thread(IncrementCounter);thread1.Start();thread2.Start();thread1.Join();thread2.Join();Console.WriteLine("Final counter value: " + counter);}static void IncrementCounter(){bool lockTaken = false;try{spinLock.Enter(ref lockTaken);  // 获取锁counter++;  // 临界区Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} incremented counter to {counter}");}finally{if (lockTaken)spinLock.Exit();  // 释放锁}}
}

4. 混合锁(Hybrid Lock)

混合锁是一种结合了互斥锁和自旋锁的锁机制,它通常用于试图在自旋锁和互斥锁之间根据具体情况进行切换,旨在提高多线程程序的效率。

混合锁的思想是:

  1. 自旋锁:在锁争用轻微、临界区代码执行时间短的情况下,使用自旋锁来减少线程挂起带来的性能开销。
  2. 互斥锁:如果自旋锁的时间过长,系统会自动切换为互斥锁,这样线程会被挂起,避免浪费过多 CPU 时间。
特点
  • 适应性强:混合锁通过平衡自旋和线程挂起的开销,避免在锁争用过于严重时造成资源浪费。
  • 自动调整:当争用变得严重时,混合锁会自动切换为互斥锁,而在争用轻微时,它会使用自旋来避免不必要的开销。
示例:C# 中没有直接的混合锁类,但可以通过自定义逻辑来实现类似功能。
using System;
using System.Threading;class Program
{private static SpinLock spinLock = new SpinLock();private static object mutex = new object();private static int counter = 0;static void Main(){Thread thread1 = new Thread(IncrementCounter);Thread thread2 = new Thread(IncrementCounter);thread1.Start();thread2.Start();thread1.Join();thread2.Join();Console.WriteLine("Final counter value: " + counter);}static void IncrementCounter(){bool lockTaken = false;try{// 尝试自旋锁if (!spinLock.TryEnter(100))  // 如果锁在 100ms 内未被获取{// 自旋失败,使用互斥锁lock (mutex){counter++;Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} incremented counter to {counter}");}}else{// 获取自旋锁counter++;Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} incremented counter to {counter}");}}finally{if (lockTaken)spinLock.Exit();}}
}

自旋锁、互斥锁和混合锁的比较

特性/锁类型互斥锁(Mutex)自旋锁(SpinLock)混合锁(Hybrid Lock)
锁获取方式阻塞,线程被挂起自旋,线程忙等待锁根据锁的争用情况自旋或阻塞
适用场景锁持有时间长、锁竞争激烈的情况锁持有时间短、锁竞争轻的情况锁持有时间变化,既有自旋又有阻塞
性能开销较高,线程挂起与恢复开销较大较低,但如果竞争严重会浪费 CPU 资源较低,可以根据情况自动调整
适用性多线程竞争较高的场景低竞争、锁持有时间短的场景高竞争情况下动态选择锁类型
总结
  • 互斥锁 适用于锁持有时间较长、竞争激烈的场景,能有效避免资源争用,但可能会导致性能瓶颈。
  • 自旋锁 适用于锁持有时间非常短的场景,能够避免线程上下文切换的开销,但如果锁争用严重,可能会浪费大量 CPU 资源。
  • 混合锁 结合了自旋锁和互斥锁的优点,能根据锁争用情况动态选择自旋或挂起,从而提供更好的性能和适应性。

选择哪种锁取决于具体的应用场景和性能需求。在高并发、高竞争的环境中,混合锁可能是最优选择,而在低竞争或快速临界区的情况下,自旋锁也许是最合适的。

5.信号量

信号量(Semaphore) 是一种用于多线程编程中的同步机制,用于控制对共享资源的访问,特别是在资源数量有限时,它能够限制并发访问的线程数目。信号量通过维护一个计数器来管理线程的访问。线程在进入临界区之前,需要检查信号量的计数值,只有计数值大于零时,线程才能进入;当线程完成工作后,信号量的计数值会增加,允许其他线程进入。

信号量的基本概念
  • 计数器:信号量内部有一个整数计数器,表示可用的资源数量或允许并发执行的线程数。
  • P操作(或称为 Wait 或 Acquire):线程尝试减少信号量的计数器。如果信号量的计数器大于零,线程会成功进入临界区,计数器减一。如果计数器为零,线程会被阻塞,直到计数器大于零。
  • V操作(或称为 Signal 或 Release):线程在完成工作后,增加信号量的计数器,允许其他被阻塞的线程继续执行。
信号量的类型
  1. 计数信号量(Counting Semaphore):计数信号量的计数器值可以是任意非负整数,表示允许访问的资源数量或线程数。例如,如果有 5 个资源或 5 个线程可以并发执行,信号量的初始值为 5。每当一个线程获得资源时,计数器减一,释放资源时计数器加一。

  2. 二值信号量(Binary Semaphore):二值信号量是计数信号量的一种特殊情况,计数器值仅为 0 或 1。它常常用于控制一个线程的互斥访问,类似于互斥锁(Mutex)。二值信号量也被称为 互斥信号量,因为它的行为与互斥锁非常相似。

信号量的应用场景
  • 控制并发访问:信号量通常用于控制某些资源的并发访问,限制同时访问某些共享资源的线程数。例如,数据库连接池中的数据库连接数有限,信号量可以用来确保不超过最大连接数。

  • 限制资源数量:例如,线程池中只允许一定数量的线程同时运行任务,超出限制的线程会被阻塞,直到其他线程完成任务并释放资源。

  • 线程同步:在一些需要线程同步的场景中,信号量可以用来控制线程的执行顺序或协调多个线程之间的操作。

示例:C# 中使用信号量

假设我们有一个共享的数据库连接池,最多只允许 3 个线程同时访问数据库。我们可以使用信号量来限制并发访问。

using System;
using System.Threading;class Program
{// 初始化信号量,最多允许 3 个线程并发访问private static Semaphore semaphore = new Semaphore(3, 3); static void Main(){// 创建并启动 5 个线程for (int i = 0; i < 5; i++){int threadId = i;Thread thread = new Thread(() => AccessDatabase(threadId));thread.Start();}}static void AccessDatabase(int threadId){Console.WriteLine($"Thread {threadId} trying to access database...");// 尝试获取信号量semaphore.WaitOne();  // 如果信号量计数器大于 0,则进入临界区,计数器减 1try{Console.WriteLine($"Thread {threadId} is accessing the database.");Thread.Sleep(2000);  // 模拟数据库访问操作Console.WriteLine($"Thread {threadId} is done with the database.");}finally{// 释放信号量semaphore.Release();  // 释放资源,信号量计数器加 1}}
}
代码解释
  1. 信号量初始化:我们使用 Semaphore(3, 3) 来创建一个信号量,初始值为 3,表示最多允许 3 个线程同时访问共享资源(这里是模拟的数据库连接)。信号量的最大值也是 3,意味着最多只能有 3 个线程持有信号量。

  2. 线程尝试访问资源:每个线程在访问数据库之前调用 semaphore.WaitOne() 来尝试获取信号量。如果信号量的计数器大于 0,线程就能成功获得信号量并进入临界区,计数器减 1;如果计数器为 0,线程会被阻塞,直到其他线程释放信号量。

  3. 线程完成后释放信号量:在 finally 块中,线程完成工作后调用 semaphore.Release() 来释放信号量,允许其他线程访问共享资源。此时,信号量计数器加 1。

信号量与其他同步机制的比较
特性/机制信号量(Semaphore)互斥锁(Mutex)读写锁(ReadWriteLock)自旋锁(SpinLock)
锁粒度用于控制资源数量用于单个资源的互斥访问分别对读和写操作加锁轻量级的锁,用于短时间临界区
适用场景控制资源数量,限流,多线程并发访问防止多线程同时访问共享资源允许多个读者同时访问,写者互斥高并发且锁持有时间短的场景
阻塞方式阻塞线程或继续执行阻塞线程阻塞线程自旋,直到获得锁
优点控制并发数量,灵活高效确保资源的独占访问提高读取性能,允许并发读取轻量级,减少上下文切换的开销
总结

信号量是一种用于控制并发访问共享资源的同步工具,特别适用于资源数量有限的场景。它通过计数器来控制允许访问的线程数量,支持灵活的线程同步与调度。根据资源需求,信号量能够控制多个线程的并发执行,避免资源争用和冲突。

6.读写锁

读写锁是一种特殊类型的锁,它允许多个线程同时读取共享数据,但在写操作时,只能有一个线程进行写操作,而且在写操作时,其他线程不能进行读操作或写操作。读写锁旨在提高读操作多、写操作少的场景下的性能,尤其是在数据读取频繁而修改较少的情况下。

读写锁的工作原理
  • 读锁:多个线程可以同时持有读锁,只要没有线程持有写锁。读锁不会阻止其他线程获取读锁。
  • 写锁:写锁是排他性的,只有一个线程可以持有写锁。并且在持有写锁时,所有其他线程(无论是读锁还是写锁)都不能访问共享资源。
  • 读写锁的基本设计思想是:在没有写操作的情况下,允许多个线程并发读取;但是一旦有写操作开始,必须保证其他线程都无法访问资源。

C# 中的 ReaderWriterLockSlim

在 C# 中,ReaderWriterLockSlim 类提供了类似的功能,用于处理并发读写操作。

  • EnterReadLock():获取读锁,允许多个线程并发读取。
  • EnterWriteLock():获取写锁,排他性锁定,阻塞所有读写操作。
using System;
using System.Threading;class Program
{static ReaderWriterLockSlim rwLock = new ReaderWriterLockSlim();static int sharedResource = 0;static void Main(){// 创建并发读取的线程Thread readThread1 = new Thread(() =>{rwLock.EnterReadLock();  // 获取读锁try{Console.WriteLine("Read Thread 1: " + sharedResource);}finally{rwLock.ExitReadLock();  // 释放读锁}});Thread readThread2 = new Thread(() =>{rwLock.EnterReadLock();  // 获取读锁try{Console.WriteLine("Read Thread 2: " + sharedResource);}finally{rwLock.ExitReadLock();  // 释放读锁}});// 创建写线程Thread writeThread = new Thread(() =>{rwLock.EnterWriteLock();  // 获取写锁try{sharedResource++;Console.WriteLine("Write Thread: " + sharedResource);}finally{rwLock.ExitWriteLock();  // 释放写锁}});// 启动线程readThread1.Start();readThread2.Start();writeThread.Start();}
}
读写锁的优势和适用场景
优势:
  1. 提高并发性能:当读操作频繁而写操作较少时,使用读写锁可以显著提高系统的并发性能。多个线程可以同时进行读操作,而无需等待锁的释放。
  2. 减少锁竞争:由于读操作不互斥,可以避免频繁的锁竞争,尤其在读操作占主导的场景中。
  3. 提供更细粒度的控制:相比传统的互斥锁(如 ReentrantLock),读写锁提供了更细粒度的锁机制,让读写操作更加高效。
适用场景:
  • 读多写少的场景:比如缓存、日志读取、数据库查询等,系统中的大多数操作是读操作,少量写操作。
  • 高并发读取:需要多个线程频繁读取共享资源,但写操作较少的应用(例如 Web 应用中的数据查询)。
  • 低并发写操作:确保在写操作发生时,不会有其他线程同时执行读操作,保持数据一致性。
需要注意的问题:
  1. 写操作可能会阻塞读操作:如果有大量的读操作而只有少数的写操作,写操作会造成较长时间的阻塞,导致性能下降。
  2. 死锁风险:在设计并发系统时,如果不小心使用了写锁嵌套或读锁嵌套,可能会导致死锁。
总结
  • 读写锁的设计旨在提高系统的并发性,特别是在读多写少的场景下。通过区分读锁和写锁,读写锁允许多个线程并行读操作,但写操作则是排他性的。
  • 它适用于需要大量读取操作且写操作相对较少的场景,可以有效减少线程之间的锁竞争,提高系统的性能。

相关文章:

.net core 线程锁,互斥锁,自旋锁,混合锁

线程锁、互斥锁、自旋锁和混合锁是多线程编程中的重要概念&#xff0c;它们用于控制对共享资源的访问&#xff0c;避免数据竞争和不一致性。每种锁有其特定的适用场景和特点。我们来逐一解释它们&#xff0c;并进行比较。 1. 线程锁&#xff08;Thread Lock&#xff09; 线程…...

大数据系列之:深入理解学习使用腾讯COS和COS Ranger权限体系解决方案,从hdfs同步数据到cos

大数据系列之&#xff1a;深入理解学习使用腾讯COS和COS Ranger权限体系解决方案&#xff0c;从hdfs同步数据到cos 对象存储COS对象存储基本概念COS Ranger权限体系解决方案部署组件COS Ranger Plugin部署COS-Ranger-Service部署COS Ranger Client部署 COSN 从hdfs同步数据到co…...

Uniapp Android 本地离线打包(详细流程)

一、简介 App 离线 SDK 暂时不支持 Kotlin&#xff0c;未来不清楚。 uniapp 提供了 云打包 与 本地打包 两种方案&#xff0c;云打包 需要排队且还有次数限制&#xff0c;本地打包 则就没有这些限制&#xff0c;而且会 本地打包 对开发 原生插件 有很大的帮助。 细节&#x…...

单片机常用外设开发流程(1)(IMX6ULL为例)

1.通过GPIO引脚控制led灯和key按钮 &#xff08;1&#xff09;设置多路复用的引脚&#xff08;SW_MUX_CTL&#xff09;也可以说是选择让引脚以哪种工作模式工作 &#xff08;2&#xff09;设置电器属性&#xff08;SW_PAD_CTL&#xff09;上拉、等等... (3)设置GPIO的方向&am…...

机器学习 学习知识点

机器学习 学习知识点 什么是消融实验&#xff08;Ablation experiment&#xff09;&#xff1f;num_step与batch_size的区别python glob.glob()函数认识python的条件判断之is not、is not None、is Nonetqdm介绍及常用方法softmax 激活函数。type_as(tesnor)Python OpenCV cv2.…...

深入了解PINN:物理信息神经网络(Physics-Informed Neural Networks)

1. 什么是PINN&#xff08;物理信息神经网络&#xff09;&#xff1f; 物理信息神经网络&#xff08;PINN&#xff0c;Physics-Informed Neural Networks&#xff09;是一类通过结合神经网络和物理方程的深度学习方法。其主要特点是将物理系统的约束条件&#xff08;如偏微分方…...

人工智能知识分享第八天-机器学习_泰坦尼克生存预估线性回归和决策树回归对比案例

泰坦尼克生存预估案例 import pandas as pd from sklearn.model_selection import train_test_split from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import classification_report import matplotlib.pyplot as plt from sklearn.tree import plot_t…...

封装/前线修饰符/Idea项目结构/package/impore

目录 1. 封装的情景引入 2. 封装的体现 3. 权限修饰符 4. Idea 项目结构 5. package 关键字 6. import 关键字 7. 练习 程序设计&#xff1a;高内聚&#xff0c;低耦合&#xff1b; 高内聚&#xff1a;将类的内部操作“隐藏”起来&#xff0c;不需要外界干涉&#xff1b…...

python中的装饰器

装饰器&#xff08;Decorator&#xff09;是 Python 中的一种语法糖&#xff0c;它允许你修改或增强函数或类的行为。下面详细解释&#xff1a; 基本概念 装饰器本质上是一个函数&#xff0c;它接受一个函数作为参数&#xff0c;并返回一个新的函数&#xff1a; def my_decor…...

HTMLElement、customElements及元素拓展

文章目录 HTMLElement 与 customElementscustomElements.define() 方法说明HTML 元素方法拓展 HTMLElement 与 customElements HTMLElement 概述 HTMLElement是一个接口&#xff0c;它表示所有HTML元素。几乎所有的HTML标签&#xff08;如<div>、<p>、<a>等…...

字玩FontPlayer开发笔记3 性能优化 大量canvas渲染卡顿问题

字玩FontPlayer开发笔记3 性能优化 大量canvas渲染卡顿问题 字玩FontPlayer是笔者开源的一款字体设计工具&#xff0c;使用Vue3 ElementUI开发&#xff0c;源代码&#xff1a; github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontpl…...

PyTorch 中 coalesce() 函数详解与应用示例

PyTorch 中 coalesce() 函数详解与应用示例 coalesce&#xff1a; 美 [ˌkoʊəˈlɛs] 合并&#xff1b;凝聚&#xff1b;联结&#xff0c;注意发音 引言 在 PyTorch 中&#xff0c;稀疏张量&#xff08;Sparse Tensor&#xff09;是一种高效存储和操作稀疏数据的方式。稀疏…...

计算机网络(第8版)第3章课后习题--透明传输

【3-11】 试分别讨论以下各种情况在什么条件下是透明传输&#xff0c;在什么条件下不是透明传 输。(提示&#xff1a;请弄清什么是“透明传输”,然后考虑能否满足其条件。) (1)普通的电话通信。 (2)互联网提供的电子邮件服务。 解 答 &#xff1a; 透明传输是指在数据传输…...

JavaScript 日期格式

在 JavaScript 中,日期格式可以通过 Date 对象进行操作和格式化。下面是一些常见的 JavaScript 日期格式及其示例: 1. ISO 8601 格式 ISO 8601 是一种标准的日期和时间表示方法,格式为 YYYY-MM-DDTHH:mm:ss.sssZ,例如: let date = new Date(); console.log(date.toISOS…...

云打印之拼多多打印组件交互协议

拼多多打印组件交互协议相关介绍如下&#xff1a; 1、打印组件下载地址 http://meta.pinduoduo.com/api/one/app/v1/lateststable?appIdcom.xunmeng.pddprint&platformwindows&subTypemain 2、socket连接端口 如果是http的话&#xff0c;端口是5000 socket new …...

Oracle数据库如何找到 Top Hard Parsing SQL 语句?

有一个数据库应用程序存在过多的解析问题&#xff0c;因此需要找到产生大量硬解析的主要语句。 什么是硬解析 Oracle数据库中的硬解析&#xff08;Hard Parse&#xff09;是指在执行SQL语句时&#xff0c;数据库需要重新解析该SQL语句&#xff0c;并创建新的执行计划的过程。这…...

浅谈棋牌游戏开发流程二:后端技术选型与基础环境搭建

一、前言&#xff1a;客户端只是台前&#xff0c;后端才是幕后“指挥中心” 在上一篇“客户端技术”中&#xff0c;我们聊到玩家看到的一切动作、动画、界面逻辑&#xff0c;都靠客户端去渲染和交互。但若没有后端的支撑&#xff0c;玩家点了“出牌”可能就像一拳打在空气里—…...

使用qiankun搭建微前端应用及踩坑

线上演示地址&#xff1a;React App 源码地址&#xff1a;https://github.com/Jiang-K-J/micro-app?tabreadme-ov-file &#xff08;帮忙点个小星星&#xff09; 主应用&#xff1a;react 18 子应用&#xff1a;vite vue3 子应用&#xff1a;react 18 安装 主应用 $ y…...

Windows 环境配置 HTTPS 服务实战

一、 环境准备 win10以上操作系统安装 Certbot申请阿里云\腾讯云域名安装 nginx 1.3以上版本 二、Certbot 安装及 SSL 证书生成 Certbot 是一个免费、开源工具&#xff0c;用于自动化在Web服务器上获取和更新SSL/TLS证书。它可以通过Let’s Encrypt服务获取免费的SSL/TLS证书…...

小程序租赁系统开发的优势与应用前景分析

内容概要 小程序租赁系统是一种新兴的数字化解决方案&#xff0c;旨在为用户提供更加便捷与高效的租赁服务。它通常包括一系列功能&#xff0c;如在线浏览、即时预定、支付功能以及用户反馈机制。这些系统在使用上极为友好&#xff0c;让用户能够轻松选择所需的商品或服务&…...

Redis(基础篇 + 实践篇 )

01 | 基本架构&#xff1a;一个键值数据库包含什么&#xff1f; Redis 作为一个内存数据存储系统&#xff0c;它的架构设计非常简洁&#xff0c;但功能非常强大。理解其核心架构对高效使用 Redis 至关重要。 客户端与服务器架构&#xff1a; 客户端通过 TCP 协议连接到 Redis …...

单片机-独立按键矩阵按键实验

1、按键介绍 按键管脚两端距离长的表示默认是导通状态&#xff0c;距离短的默认是断开状态&#xff0c; 如果按键按下&#xff0c;初始导通状态变为断开&#xff0c;初始断开状态变为导通 我们开发板是采用软件消抖&#xff0c;一般来说一个简单的按键消抖就是先读取按键的状…...

我用AI学Android Jetpack Compose之入门篇(1)

这篇我们先来跑通第一个Android Jetpack Compose工程&#xff0c;现在新版本的Android Studio&#xff0c;新建工程选择Empty Activity默认就会开启Jetpack Compose的支持&#xff0c;再次声明&#xff0c;答案来自 通义千问Ai 文章目录 1.用Android Jetpack Compose需要安装什…...

简单的生产数据库重连策略优化

简单的druid生产数据库重连策略优化 1. 需求 我们生产环境有一次在大量请求拥堵后&#xff0c;好多数据库操作都超时了&#xff0c;在此之后数据库的连接池不能正常的获取数据库连接了&#xff0c;我们确认了数据库服务是没有问题的&#xff0c;那么就是连接池的配置有问题&a…...

STM32-笔记37-吸烟室管控系统项目

一、项目需求 1. 使用 mq-2 获取环境烟雾值&#xff0c;并显示在 LCD1602 上&#xff1b; 2. 按键修改阈值&#xff0c;并显示在 LCD1602 上&#xff1b; 3. 烟雾值超过阈值时&#xff0c;蜂鸣器长响&#xff0c;风扇打开&#xff1b;烟雾值小于阈值时&#xff0c;蜂鸣器不响…...

2025-01-04 Unity插件 YodaSheet1 —— 插件介绍

文章目录 1 介绍2 工作原理2.1 ScriptableObject -> YadeSheetData2.2 YadeDatabase 存储多个 YadeSheetData 3 用途4 缺点5 推荐 1 介绍 ​ Yade 提供类似于 Excel 或者 Google Sheets 的表格编辑器&#xff0c;可以轻松地在 Unity 编辑器中 编辑&#xff0c;搜索&#xf…...

电子电气架构 --- 安全相关内容汇总

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…...

科研绘图系列:R语言单细胞数据常见的可视化图形

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理图1图2图3图4图5图6系统信息参考介绍 单细胞数据常见的可视化图形 因为本教程是单细胞数据,因此运行本画图脚本需要电脑的内存最少32Gb 加载…...

【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 2:基础知识

目录 1 预热1.1 记号1.2 分类器计算过载问题 2 多头编码&#xff08;MHE&#xff09;2.1 标签分解2.2 多头组合&#xff08;Multi-Head Combination&#xff09; 论文&#xff1a;Multi-Head Encoding for Extreme Label Classification 作者&#xff1a;Daojun Liang, Haixia …...

Flink使用

Window下启动支持 下载或复制老版本的放在bin目录下即可&#xff1b; flink.bat echo off setlocalSET bin%~dp0 SET FLINK_HOME%bin%.. SET FLINK_LIB_DIR%FLINK_HOME%\lib SET FLINK_PLUGINS_DIR%FLINK_HOME%\pluginsSET JVM_ARGS-Xmx512mSET FLINK_JM_CLASSPATH%FLINK_LI…...

一种可复用的AI提效方案:AI点灯

在当今飞速发展的时代&#xff0c;AI技术正不断渗透到我们生活的各个层面&#xff0c;深刻改变着传统的工作方式和生活模式。面对这一重大变革&#xff0c;我们不能被动观望或抗拒&#xff0c;而应积极拥抱AI&#xff0c;将其作为成长的助力。只有与AI协同发展&#xff0c;才能…...

Django 模型

Django 模型 Django 模型是 Django 框架的核心组件之一,它用于定义应用程序的数据结构。在 Django 中,模型是 Python 类,通常继承自 django.db.models.Model。每个模型类代表数据库中的一个表,模型类的属性对应表中的字段。 1. 创建模型 创建 Django 模型非常简单。首先…...

【MySQL 探索者日志 】第二弹 —— 数据库基础

MySQL系列学习笔记&#xff1a; MySQL探索者日志__Zwy的博客-CSDN博客 各位于晏&#xff0c;亦菲们&#xff0c;请点赞关注&#xff01; 我的个人主页&#xff1a; _Zwy-CSDN博客 目录 1、MySQL服务器&#xff0c;数据库&#xff0c;表关系 2、MySQL登录连接服务器 3、MyS…...

【51单片机-零基础chapter1】

安装软件(配套的有,不多赘述) 1.管理员身份运行keil和破解软件kegen 将CID代码复制粘贴到 一定要管理员方式,不然会error 插入板子 我的电脑,管理 1.如果是拯救者,查看端口,如果没有则显示隐藏 2.苹果不知道,好像不可以 3.其他电脑在"其他设备找" (注:本人在校已…...

stm32的掉电检测机制——PVD

有时在一些应用中&#xff0c;我们需要检测系统是否掉电了&#xff0c;或者要在掉电的瞬间需要做一些处理。 STM32内部自带PVD功能&#xff0c;用于对MCU供电电压VDD进行监控。 STM32就有这样的掉电检测机制——PVD(Programmable Voltage Detecter)&#xff0c;即可编程电压检…...

电脑steam api dll缺失了怎么办?

电脑故障解析与自救指南&#xff1a;Steam API DLL缺失问题的全面解析 在软件开发与电脑维护的广阔天地里&#xff0c;我们时常会遇到各种各样的系统报错与文件问题&#xff0c;其中“Steam API DLL缺失”便是让不少游戏爱好者和游戏开发者头疼的难题之一。作为一名深耕软件开…...

Kotlin 协程基础知识总结七 —— Flow 与 Jetpack Paging3

专题分为五大块&#xff1a; Paging3 的结构组成Flow 与 Paging3下拉刷新上拉刷新离奇 Bug上游数据缓存 Demo 会还原开发迭代的过程&#xff0c;不会直接一步到位。 1、Paging3 加载数据流程 &#xff08;P105&#xff09;Paging3 的简介详情可参考官方文档 Paging 库概览&…...

使用JMeter玩转tidb压测

作者&#xff1a; du拉松 原文来源&#xff1a; https://tidb.net/blog/3f1ada39 一、前言 tidb是mysql协议的&#xff0c;所以在使用过程中使用tidb的相关工具连接即可。因为jmeter是java开发的相关工具&#xff0c;直接使用mysql的jdbc驱动包即可。 二、linux下安装jmet…...

音视频入门基础:MPEG2-PS专题(3)——MPEG2-PS格式简介

一、引言 本文对MPEG2-PS格式进行简介。 进行简介之前&#xff0c;请各位先下载MPEG2-PS的官方文档。ITU-T和ISO/IEC都分别提供MPEG2-PS的官方文档。但是ITU提供的文档是免费的&#xff0c;ISO/IEC是付费的&#xff0c;所以我们主要阅读ITU提供的官方文档&#xff0c;比如较新…...

ETCD渗透利用指南

目录 未指定使用put操作报错 未指定操作版本使用get报错 首先etcd分为两个版本v2和v3&#xff0c;不同的API结果无论是访问URL还是使用etcdctl进行通信&#xff0c;都会导致问题&#xff0c;例如使用etcdctl和v3进行通信&#xff0c;如果没有实名ETCDCTL_API3指定API版本会直接…...

Python安装(新手详细版)

前言 第一次接触Python&#xff0c;可能是爬虫或者是信息AI开发的小朋友&#xff0c;都说Python 语言简单&#xff0c;那么多学一些总是有好处的&#xff0c;下面从一个完全不懂的Python 的小白来安装Python 等一系列工作的记录&#xff0c;并且遇到的问题也会写出&#xff0c…...

SQL 中复杂 CASE WHEN 嵌套逻辑优化

目标&#xff1a;优化复杂的 CASE WHEN 逻辑&#xff0c;提升 SQL 语句的可读性与执行效率&#xff0c;减少多层嵌套带来的复杂性。 1. CASE WHEN 的常见问题 嵌套过深&#xff1a;多个条件判断嵌套&#xff0c;难以阅读和维护。重复逻辑&#xff1a;相似逻辑在多个分支中重复…...

【专题】2024年出口跨境电商促销趋势白皮书报告汇总PDF洞察(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p38722 在当今全球化加速演进、数字经济蓬勃发展的大背景下&#xff0c;跨境电商行业正以前所未有的态势重塑国际贸易格局&#xff0c;成为各方瞩目的焦点领域。 根据亚马逊发布的《2024年出口跨境电商促销趋势白皮书》&#xff0c;…...

C# 设计模式(结构型模式):代理模式

C# 设计模式&#xff08;结构型模式&#xff09;&#xff1a;代理模式 在软件开发中&#xff0c;有时我们需要通过某种方式间接地访问一个对象&#xff0c;这时就可以使用代理模式&#xff08;Proxy Pattern&#xff09;。代理模式通过引入一个代理对象来控制对目标对象的访问…...

单片机复位电路基本理解教程文章·含上拉电阻理解电容开路理解!!!

目录 常见复位电路种类 复位电路电阻上拉理解 电容储能断路理解 ​​​​​​​ ​​​​​​​ 编写不易&#xff0c;仅供学习&#xff0c;请勿搬运&#xff0c;感谢理解 常见元器件驱动电路文章专栏连接 LM7805系列降压芯片驱动电路降压芯片驱动电路详解-…...

深入浅出:事件监听中的适配器模式

1. 为什么需要适配器模式&#xff1f; 在Java的事件监听器设计中&#xff0c;许多接口有多个抽象方法。例如&#xff0c;MouseListener 接口有 5 个方法&#xff0c;KeyListener 接口有 3 个方法。如果我们只关心其中的一个方法&#xff08;例如&#xff0c;鼠标点击事件&…...

常用LabVIEW算法及应用

在LabVIEW项目中&#xff0c;算法的应用是提高系统性能、实现特定功能、完成复杂任务的核心。LabVIEW作为一种图形化编程语言&#xff0c;允许用户通过直观的图形编程来实现各种复杂的算法。这些算法广泛应用于控制系统、数据采集、信号处理、图像处理、机器学习等领域。了解常…...

VTK知识学习(28)-区域提取

1、感兴趣区域(Volume ofInterest&#xff0c;VOI) 它是图像内部的一块子区域。在VTK中&#xff0c;vtkExtractVOI 类可根据用户指定的区域范围提取子图像。该Filter 的输入和输出都是一个vtkImageData,因此其结果可以直接作为图像保存。 代码&#xff1a; private void Test…...

基于Spring Boot + Vue3实现的在线汽车保养维修预约管理系统源码+文档

前言 基于Spring Boot Vue3实现的在线汽车保养维修预约管理系统是一种前后端分离架构的应用&#xff0c;它结合了Java后端开发框架Spring Boot和现代JavaScript前端框架Vue.js 3.0的优势。这样的系统可以为汽车服务站提供一个高效的平台来管理客户的预约请求 技术选型 系统…...

CAN201 Introduction to Networking(计算机网络)Pt.4 链路层

文章目录 5. Link Layer&#xff08;链路层&#xff09;5.1 Services of link layer&#xff08;链路层的服务&#xff09;5.2 Error detection and correction&#xff08;错误检测和纠正&#xff09;5.2.1 Partity Checks&#xff08;奇偶检验&#xff09;5.2.2 Checksum&…...