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

Linux系统编程--线程同步

目录

一、前言

二、线程饥饿

三、线程同步

四、条件变量

1、cond

2、条件变量的使用

五、条件变量与互斥锁


一、前言

        上篇文章我们讲解了线程互斥的概念,为了防止多个线程同时访问一份临界资源而出问题,我们引入了线程互斥,线程互斥其实就是多个线程同时争抢一份资源,谁抢到了就是谁的,抢不到的只能等待着下一次抢。虽然解决了有多个线程同时访问同一资源所产生的问题,但是我们思考一下这样子合理吗?不合理,这会产生另一种问题——线程饥饿。

二、线程饥饿

       那么线程饥饿是什么呢?为了便于理解,我们可以极端地考虑问题,假设在多线程情况下,存在着两类优先级不同的线程,一类线程的优先级非常高,另一类的线程的优先级非常低,他们开始同时争抢临界资源,假设高优先级的线程拿到了资源,上了锁之后,其他的线程只能等。直到该线程使用完临近资源后解锁,接着所有线程又开始争抢资源,而高优先级的线程因为其优先性会再一次争抢到资源,如循环往复,导那些低优先级的线程总是在等待中,永远拿不到或者很少次数拿到资源,这样被称为饥饿或者饿死。这种争抢临界资源的方式虽然是没有什么错误,但是总归来说是不合理的。

三、线程同步

       在线程只使用互斥的方式去访问临界资源的时候,就可能会出现某些线程饥饿的情况。那么在操作系统中有没有一种机制,在某一时刻既可以只让一个线程去访问临界资源,但是又可以让所有的的线程按照一定的顺序访问资源呢?所有的线程就像排队一样一个个轮流访问资源,当某一线程访问玩临界资源的时候,他就去队尾等待。这样所有的线程的执行流都可以访问到资源,从而杜绝了线程饥饿的问题。  这样的机制叫做——同步,即线程同步,在保证临界资源安全的前提下,让执行流访问临界资源具有一定的顺序性

互斥也是同步的一种,尽管只采用互斥后执行流还是乱序的,但是互斥保证了同一时刻只能有一个线程访问临界资源。但是本篇文章在介绍同步的时候,会将两者分开,即同步不包括互斥。

四、条件变量

 那么同步是怎么实现的呢?同步离不开一个东西——条件变量条件变量是一种可以实现线程同步的机制,通过条件变量,可以实现让线程有序的访问临界资源

条件变量,顾名思义它是一个执行的“条件”,当线程需要访问临界资源时,如果临界资源不满足一定的条件,那就让线程进行等待,如果满足条件,则让线程继续恢复执行的机制。它是一个 pthread_cond_t 结构体类型的变量,并且在 pthread 库中也提供了一些条件变量相关的接口


1、cond

cond即 英文单词 condition 的缩写,译为条件。

pthread_cond_t 是定义条件变量的类型。

条件变量的使用是和互斥锁差不多的。

  • 条件变量的初始化可以和互斥量相同有两种,一种是调用接口 pthread_cond_init() 初始化,第一个参数是条件变量的地址,第二个参数是条件变量的属性(暂时不考虑)。需要注意的是,用该接口初始化的条件变量在不需要使用的时候,需要调用 pthread_cond_destroy() 接口来销毁掉。 
  • 使用宏初始化的条件变量就不用手动调用接口来销毁了。

使用条件变量等待的接口: 

  •  这么多等待的接口中 pthread_cond_wait() 接口是最常用的,它是pthread库提供的使用条件变量等待的接口,线程调用此接口,线程就会立即进入等待。
  • pthread_cond_timedwait() 也是pthread提供给的使用条件变量等待的接口,不过看他的名字也知道它是一种定时让线程等待的接口,即可以通过该接口设置一定的时间,在此时间内让线程等待,如果此时间内,条件满足了,线程就会被自动唤醒,继续执行代码
  • 我们可以看到这两个接口的参数中都有 互斥锁 ,他们是和互斥锁一起配合使用的。

上面讲到了两个通过条件变量让线程进行等待的接口,既然有等待的接口,那么自然就存在着通过条件变量去唤醒线程的接口。如下

  • pthread_cond_signal(),调用该接口可以让某个通过指定条件变量陷入等待的线程被唤醒。
  • pthread_cond_broadcast(),调用此接口,可以让通过指定条件变量陷入等待的所有线程被唤醒

2、条件变量的使用

下面我们简单使用一下条件变量,主要看看它是怎么用的。

#include<iostream>
#include<pthread.h>
#include<unistd.h>
using std::cin;
using std::cout;
using std::endl;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;//利用宏初始化全局互斥锁,不用销毁
pthread_cond_t cond;//定义全局条件变量void* Callback(void* argc)
{pthread_detach(pthread_self());//这里让线程自动分离,我们后面不回收它const char* name=(const char*)argc;while(true){pthread_cond_wait(&cond,&mutex);//使用条件变量让进程在这里等待cout<<name<<",tid::"<<pthread_self()<<",running"<<endl;}return nullptr;}
int main()
{pthread_cond_init(&cond,nullptr);//初始化条件变量pthread_t tid1,tid2,tid3;pthread_create(&tid1,nullptr,Callback,(void*)"thread 1");pthread_create(&tid2,nullptr,Callback,(void*)"thread 2");pthread_create(&tid3,nullptr,Callback,(void*)"thread 3");while(true){char c='a';cout<<"Please input your command:(N/Q)::";cin>>c;if(c=='N'|c=='n'){pthread_cond_signal(&cond);//唤醒单个的线程}elsebreak;usleep(1000);//让主线程在这里等待一下防止多线程之间的打印干扰}pthread_cond_destroy(&cond);//销毁条件变量return 0;}

运行结果:

可以看到pthread_cond_signal()对线程的唤醒是以一定顺序来进行的。当然我们也可以使用pthread_cond_broadcast()来广播唤醒所有的在等待中的线程。


上面演示的是cond变量的简单使用,我们在函数中直接让它进行等待,事实上在实际的使用中,当有条件变量不满足时,才会使用条件变量让线程等待。

我们可以设置一个退出条件 quit,为真时即为满足,否则不满足。不满足条件时,就让线程等待,满足条件就唤醒线程。

#include<iostream>
#include<pthread.h>
#include<unistd.h>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond;
volatile bool quit=false;
void* Callback(void* argc)
{pthread_detach(pthread_self());const char* name=(const char*)argc;while(!quit){pthread_cond_wait(&cond,&mutex);cout<<name<<",tid::"<<pthread_self()<<",running"<<endl;}
//下面释放锁的操作是因为pthread_cond_wait()接口在等待时会释放锁资源,然后被唤醒的时候又会竞争锁资源,如果线程退出条件满足了,在退出的时候,仍然是对临界资源上了锁,所以在退出之前需要先解锁,不然会导致死锁(如果不提前进行分离)pthread_mutex_unlock(&mutex);cout<<name<<",tid::"<<pthread_self()<<",end"<<endl;return nullptr;}
int main()
{pthread_cond_init(&cond,nullptr);pthread_t tid1,tid2,tid3;pthread_create(&tid1,nullptr,Callback,(void*)"thread 1");pthread_create(&tid2,nullptr,Callback,(void*)"thread 2");pthread_create(&tid3,nullptr,Callback,(void*)"thread 3");while(true){char c='a';cout<<"Please input your command:(N/Q)::";cin>>c;if(c=='N'|c=='n'){pthread_cond_broadcast(&cond);}else{quit=true;pthread_cond_broadcast(&cond);break;}usleep(1000);}pthread_cond_destroy(&cond);return 0;}

这里比之前的简单应用主要多了一个解锁操作。且在 输入非N或n时,唤醒线程,再让线程判断一下条件是否满足。

可以看到 使用条件变量可以让多线程的执行具有一定的顺序性,即可以实现同步。同步与互斥是互补的关系。

五、条件变量与互斥锁

在我们上面所举的例子当中,让线程根据条件变量进行等待的接口都是需要同时用到条件变量和互斥锁,使用到条件变量这是无可厚非的,但是为什么需要用到互斥锁呢?

首先,条件等待是使用条件变量实现同步等待的一种方式,如果只存在一个线程的话,当条件不满足时,线程就会一直等待下去,因为唯一的线程在等待,并没有其他的线程修改条件,所以在线程等待的时候,条件也不可能满足。

所以这里需要的是一个使得条件变得满足,然后再唤醒等待的线程。这里的条件实际上就是指 线程对应的需要访问的临界资源的状态,就像我们在介绍互斥时的抢票动作,需要保证只有在票数大于0时,才能抢票。

而条件是不可能无缘无故在没有变化的情况下就自己满足的,所以条件满足势必会存在着临界资源数据的变化,所以需要用互斥锁来保护临界资源。

所以线程在判断条件满足之前需要先上锁,然后再判断条件是否满足,如果不满足则条件等待并解锁,接着让其他可以让条件满足的线程获取锁,条件满足之后,再唤醒刚才等待的线程并解锁。让刚被唤醒的线程再次取到锁,判断条件是否满足,满足就去执行,否则再次陷入等待。整个过程的重点就是谁需要访问临界资源就上锁,谁不需要就解锁,即保证在整个的过程当中临界资源始终是被保护着的。

整个的过程当中,除了第一次对临界资源上锁和最后一次对临界资源解锁,中间所有的上锁和解锁操作都是由pthread_cond_wait()操作完成的,在线程需要等待的时候调用pthread_cond_wait()解锁并等待,在线程被唤醒时,会自动再去竞争锁,解锁和上锁操作都是在pthread_cond_wait()内部进行的。这就是为什么我们在上面的例子中在多线程退出时,需要在条件满足时先释放锁,然后再让线程退出。

pthread_cond_wait()接口需要执行释放锁和竞争锁的操作,所以需要先看到锁这也是为什么该接口需要和互斥锁一起使用。

相关文章:

Linux系统编程--线程同步

目录 一、前言 二、线程饥饿 三、线程同步 四、条件变量 1、cond 2、条件变量的使用 五、条件变量与互斥锁 一、前言 上篇文章我们讲解了线程互斥的概念&#xff0c;为了防止多个线程同时访问一份临界资源而出问题&#xff0c;我们引入了线程互斥&#xff0c;线程互斥其实…...

李沐《动手学深度学习》——14.9. 用于预训练BERT的数据集——wiki数据集问题以及存在的其他问题

问题1&#xff1a;出现"file is not a zip file" 原因是链接已经失效。 解决方法&#xff1a;打开下面链接自行下载&#xff0c;需要魔法。下载完解压到特定位置。 下载链接&#xff1a;项目首页 - Wikitext-2-v1数据包下载:Wikitext-2-v1 数据包下载本仓库提供了一…...

【英伟达AI论文】多模态大型语言模型的高效长视频理解

摘要&#xff1a;近年来&#xff0c;基于视频的多模态大型语言模型&#xff08;Video-LLMs&#xff09;通过将视频处理为图像帧序列&#xff0c;显著提升了视频理解能力。然而&#xff0c;许多现有方法在视觉主干网络中独立处理各帧&#xff0c;缺乏显式的时序建模&#xff0c;…...

深入理解 DOM 元素

深入理解 DOM 元素&#xff1a;构建动态网页的基石 在网页开发的世界里&#xff0c;DOM&#xff08;Document Object Model&#xff0c;文档对象模型&#xff09;元素宛如一座桥梁&#xff0c;连接着静态的 HTML 结构与动态的 JavaScript 交互逻辑。它让原本呆板的网页变得鲜活…...

linux如何判断进程对磁盘是随机写入还是顺序写入?

模拟工具&性能测试工具&#xff1a;fio fio参数说明&#xff1a; filename/dev/sdb1&#xff1a;测试文件名称&#xff0c;通常选择需要测试的盘的data目录。 direct1&#xff1a;是否使用directIO&#xff0c;测试过程绕过OS自带的buffer&#xff0c;使测试磁盘的结果更真…...

实现静态网络爬虫(入门篇)

一、了解基本概念以及信息 1.什么是爬虫 爬虫是一段自动抓取互联网信息的程序&#xff0c;可以从一个URL出发&#xff0c;访问它所关联的URL&#xff0c;提取我们所需要的数据。也就是说爬虫是自动访问互联网并提取数据的程序。 它可以将互联网上的数据为我所用&#xff0c;…...

[Web]get请求和post请求

Get get请求的特点是&#xff1a; 1.所有的参数都通过URL进行传递。其中传输的参数的书写的格式为?key1value1&key2value2。具体示例&#xff1a;https://example.com/search?qapple&limit10。访问的时候&#xff0c;先写/xxx&#xff0c;确定本次请求要访问的资源u…...

【落羽的落羽 C++】C++入门基础:引用,内联,nullptr

文章目录 一、引用1. 引用的概念2. 引用的特点3. 引用的使用4. const引用5. 引用和指针 二、inline内联三、nullptr 一、引用 1. 引用的概念 引用是C中的一个较为重要的概念。它是给已存在变量取的“别名”&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引…...

RabbitMQ应用问题大全(精心整理版)

前言 其实这部分知识我是整理在语雀上了&#xff0c;这里是直接复制粘贴过来的。不是很好阅读&#xff0c;可以直接点下方链接去语雀看&#xff0c;那个看的会舒服很多。 https://www.yuque.com/g/ngioig/upbg6b/fkarhyo8fpgrtyq8/collaborator/join?tokenGvlO0di8KaIfO8aF&am…...

【人工智能】卷积神经网络的奥秘:深度学习的视觉革命

卷积神经网络(CNN)是深度学习中处理图像、视频等高维数据的主流模型,因其局部特征提取和参数共享特性而效率高且效果优异。本文深入探讨了CNN的理论基础,包括卷积操作、池化层、激活函数和全连接层的数学原理,并通过LaTeX公式推导其前向传播和反向传播过程。接着,我们提供…...

掌握MiniQMT:程序化下单与撤单的高效实现

掌握MiniQMT&#xff1a;程序化下单与撤单的高效实现 &#x1f680;量化软件开通 &#x1f680;量化实战教程 在量化交易领域&#xff0c;程序化下单与撤单是实现自动化交易策略的关键环节。通过MiniQMT平台&#xff0c;我们可以高效地执行这些操作&#xff0c;从而快速响应…...

【高级篇】大疆Pocket 3加ENC编码器实现无线RTMP转HDMI进导播台

【高级篇】大疆Pocket 3加ENC编码器实现无线RTMP转HDMI进导播台 文章目录 准备工作连接设备RTMP概念ENCSHV2推流地址设置大疆Pocket 3直播设置总结 老铁们好&#xff01; 很久没写软文了&#xff0c;今天给大家带了一个干货&#xff0c;如上图&#xff0c;大疆Pocket 3加ENC编…...

Nacos学习笔记-占位符读取其他命名空间内容

Nacos当前命名空间下的配置文件需要跨命名空间读取其他配置文件的内容。可以先通过Nacos提供的API接口获取配置文件内容&#xff0c;然后解析数据将其放入环境的PropertySource中。 相关依赖包 <!-- Nacos依赖包 --> <dependency><groupId>com.alibaba.clo…...

每天五分钟深度学习框架PyTorch:使用残差块快速搭建ResNet网络

本文重点 前面我们使用pytorch搭建了残差块&#xff0c;本文我们更进一步&#xff0c;我们使用残差块搭建ResNet网络&#xff0c;当学会如何搭建残差块之后&#xff0c;搭建ResNet就会非常简单了&#xff0c;因为ResNet就是由多个残差块组成的。 残差块 残差块我们前面已经介…...

python操作java文件的一种方法

对于python操作java代码的场景来说&#xff0c;比较多的可能就是涉及加密的场景&#xff0c;尤其涉及到登录的场景&#xff0c;对于输入的账号密码可能会涉及到加密&#xff0c;如果开发告诉我们如何加密&#xff0c;那么&#xff0c;OK&#xff0c;我们可以直接通过代码去实现…...

自然语言处理:最大期望值算法

介绍 大家好&#xff0c;博主又来给大家分享知识了&#xff0c;今天给大家分享的内容是自然语言处理中的最大期望值算法。那么什么是最大期望值算法呢&#xff1f; 最大期望值算法&#xff0c;英文简称为EM算法&#xff0c;它的核心思想非常巧妙。它把求解模型参数的过程分成…...

leetcode-sql数据库面试题冲刺(高频SQL五十题)

题目&#xff1a; 197.上升的温度 表&#xff1a; Weather ---------------------- | Column Name | Type | ---------------------- | id | int | | recordDate | date | | temperature | int | ---------------------- id 是该表具有唯一值的列。 没有具有相同 recordDate …...

开发者社区测试报告(功能测试+性能测试)

功能测试 测试相关用例 开发者社区功能背景 在当今数字化时代&#xff0c;编程已经成为一项核心技能&#xff0c;越来越多的人开始学习编程&#xff0c;以适应快速变化的科技 环境。基于这一需求&#xff0c;我设计开发了一个类似博客的论坛系统&#xff0c;专注于方便程序员…...

环形链表问题的探究与代码实现

在数据结构与算法的学习中&#xff0c;环形链表是一个经典的问题。它不仅考察对链表这种数据结构的理解&#xff0c;还涉及到指针操作和逻辑推理。本文将结合代码和图文&#xff0c;深入分析如何判断链表中是否有环以及如何找到环的入口点。 目录 一、判断链表中是否有环 …...

【C++】vector(下):vector类的模拟实现(含迭代器失效问题)

文章目录 前言一、vector类的常用接口的模拟实现1.头文件&#xff08;my vector.h&#xff09;整体框架2.模拟实现vector类对象的常见构造3.模拟实现vector iterator4.模拟实现vector类对象的容量操作5.模拟实现vector类对象的访问6.模拟实现vector类对象的修改操作 二、vector…...

NLTK和jieba

NLTK与jieba概述 自然语言处理&#xff08;NLP&#xff09;领域是计算机科学领域与人工智能领域中的一个重要方向&#xff0c;主要研究方向是实现人与计算机之间用自然语言进行有效通信的各种理论和方法。 在自然语言处理领域中&#xff0c;文本类型的数据占据着很大的市场&a…...

Java后端高频面经——计算机网络

TCP/IP四层模型&#xff1f;输入一个网址后发生了什么&#xff0c;以百度为例&#xff1f;&#xff08;美团&#xff09; &#xff08;1&#xff09;四层模型 应用层&#xff1a;支持 HTTP、SMTP 等最终用户进程传输层&#xff1a;处理主机到主机的通信&#xff08;TCP、UDP&am…...

CSDN博客:Markdown编辑语法教程总结教程(中)

❤个人主页&#xff1a;折枝寄北的博客 Markdown编辑语法教程总结 前言1. 列表1.1 无序列表1.2 有序列表1.3 待办事项列表1.4 自定义列表 2. 图片2.1 直接插入图片2.2 插入带尺寸的图片2.3 插入宽度确定&#xff0c;高度等比例的图片2.4 插入高度确定宽度等比例的图片2.5 插入居…...

Springboot redis bitMap实现用户签到以及统计,保姆级教程

项目架构&#xff0c;这是作为demo展示使用&#xff1a; Redis config&#xff1a; package com.zy.config;import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.Ob…...

AI Agent系列(一) - Agent概述

AI Agent系列【一】 前言一、AI代理的特点二、 AI Agent的技术框架三、 开源自主代理 前言 AI Agent&#xff0c;即人工智能代理&#xff0c;一般直接叫做智能体 百度百科给AI Agent定义为&#xff1a; “以大语言模型为大脑驱动的系统&#xff0c;具备自主理解、感知、规划、…...

Scala 中trait的线性化规则(Linearization Rule)和 super 的调用行为

在 Scala 中&#xff0c;特质&#xff08;Trait&#xff09;是一种强大的工具&#xff0c;用于实现代码的复用和组合。当一个类混入&#xff08;with&#xff09;多个特质时&#xff0c;可能会出现方法冲突的情况。为了解决这种冲突&#xff0c;Scala 引入了最右优先原则&#…...

【Linux系统编程】初识系统编程

目录 一、什么是系统编程1. 系统编程的定义2. 系统编程的特点3. 系统编程的应用领域4. 系统编程的核心概念5. 系统编程的工具和技术 二、操作系统四大基本功能1. 进程管理&#xff08;Process Management&#xff09;2. 内存管理&#xff08;Memory Management&#xff09;3. 文…...

Unsloth - 动态 4 bit 量化

文章目录 &#x1f494; 量化可能会破坏模型&#x1f999; Llama 3.2 Vision 细节Pixtral (12B) 视觉&#x1f999; Llama 3.2 (90B) 视觉指令 本文翻译自&#xff1a;Unsloth - Dynamic 4-bit Quantization &#xff08;2024年12月4日 Daniel & Michael https://unsloth.…...

技术领域,有许多优秀的博客和网站

在技术领域&#xff0c;有许多优秀的博客和网站为开发者、工程师和技术爱好者提供了丰富的学习资源和行业动态。以下是一些常用的技术博客和网站&#xff0c;涵盖了编程、软件开发、数据科学、人工智能、网络安全等多个领域&#xff1a; 1. 综合技术博客 1.1 Medium 网址: ht…...

黑金风格人像静物户外旅拍Lr调色教程,手机滤镜PS+Lightroom预设下载!

调色教程 针对人像、静物以及户外旅拍照片&#xff0c;运用 Lightroom 软件进行风格化调色工作。旨在通过软件中的多种工具&#xff0c;如基本参数调整、HSL&#xff08;色相、饱和度、明亮度&#xff09;调整、曲线工具等改变照片原本的色彩、明度、对比度等属性&#xff0c;将…...

Manus 与鸿蒙 Next 深度融合:构建下一代空间计算生态

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/north 文章目录 一、技术融合背景与意义1.1 技术栈协同优势1.2 典型应用场景 二、系统架构设计2.1 整体架构图…...

并查集模板

注意理解路径压缩 static class UnionFind {int[] fa;public UnionFind(int n) {fa new int[n];for (int i 0; i < n; i) {fa[i] i;}}public int find(int i) {if (fa[i] ! i) {fa[i] find(fa[i]);}return fa[i];}public void union(int i, int j) {int fai find(i);in…...

推流项目的ffmpeg配置和流程重点总结一下

ffmpeg的初始化配置&#xff0c;在合成工作都是根据这个ffmpeg的配置来做的&#xff0c;是和成ts流还是flv&#xff0c;是推动远端还是保存到本地&#xff0c; FFmpeg 的核心数据结构&#xff0c;负责协调编码、封装和写入操作。它相当于推流的“总指挥”。 先来看一下ffmpeg的…...

使用 Python 开发的简单招聘信息采集系统

以下是一个使用 Python 开发的简单招聘信息采集系统,它包含用户登录、招聘信息收集和前后端交互的基本功能。我们将使用 Flask 作为后端框架,HTML 作为前端页面。 项目结构 recruitment_system/ ├── app.py ├── templates/ │ ├── login.html │ ├── index…...

Selenium库打开指定端口(9222、9333等)浏览器【已解决!!!】

就是在写动态爬虫爬取数据的过程中&#xff0c;如果用selenium的话&#xff0c;有一个缺点&#xff0c;就是当我们去测试一个网站能不能爬取&#xff0c;它都会重新换端口打开一个浏览器&#xff0c;不会使用上一次使用的浏览器&#xff0c;在实际使用过程中这样调试很烦&#…...

Android MVI架构模式详解

MVI概念 MVI&#xff08;Model-View-Intent&#xff09;是一种Android应用架构模式&#xff0c;旨在通过单向数据流和不可变性来简化应用的状态管理。MVI的核心思想是将用户操作、状态更新和界面渲染分离&#xff0c;确保应用的状态可预测且易于调试。 MVI的核心组件 Model&a…...

低代码开发直聘管理系统

低代码 DeepSeek 组合的方式开发直聘管理系统&#xff0c;兼职是开挂的存在。整个管理后台系统 小程序端接口的输出&#xff0c;只花了两个星期不到。 一、技术栈 后端&#xff1a;SpringBoot mybatis MySQL Redis 前端&#xff1a;Vue elementui 二、整体效果 三、表结…...

LVGL开发说明

准备工作 LVGL图形化工具&#xff1a;Gui-Guider-Setup-1.8.0-GA.exeLVGL库&#xff1a;lvgl-release-v8.3屏幕触摸驱动&#xff1a;CST816屏幕驱动&#xff1a;ST7789屏幕尺寸&#xff1a;320 * 170 触发事件 按键的点击事件 添加点击事件 触摸屏点击对应的按键后就会触发回…...

推荐优秀的开源软件合集

在信息化高度发达的今天&#xff0c;数据安全与远程协作变得越来越重要。很多企业和个人都在寻找可替代商业闭源软件的开源解决方案。今天&#xff0c;我们向大家推荐几款优秀的开源软件&#xff0c;涵盖私有云存储、远程桌面、团队协作、内容管理等多个领域。 1. Nextcloud —…...

代码随想录刷题day41|(二叉树篇)二叉树的最大深度(递归)

目录 一、二叉树理论基础 二、二叉树的深度和高度 三、递归和迭代思路 3.1 递归法 3.2 迭代法 四、相关算法题目 五、总结 一、二叉树理论基础 详见&#xff1a;代码随想录刷题day34|&#xff08;二叉树篇&#xff09;二叉树的递归遍历-CSDN博客 二、二叉树的深度和高…...

向量内积(点乘)和外积(叉乘)

文章目录 1. 向量的内积&#xff08;点积&#xff09;1.1 定义1.2 几何意义表征两个向量的投影关系计算向量夹角的余弦值 1.3 重要性质1.4 应用场景 2. 向量的外积&#xff08;叉积&#xff09;2.1 定义&#xff08;仅适用于三维空间&#xff09;2.2 几何意义2.3 重要性质2.4 应…...

PDF转JPG(并去除多余的白边)

首先&#xff0c;手动下载一个软件&#xff08;poppler for Windows&#xff09;&#xff0c;下载地址&#xff1a;https://github.com/oschwartz10612/poppler-windows/releases/tag/v24.08.0-0 否则会出现以下错误&#xff1a; PDFInfoNotInstalledError: Unable to get pag…...

【无人机路径规划】基于麻雀搜索算法(SSA)的无人机路径规划(Matlab)

效果一览 代码获取私信博主基于麻雀搜索算法&#xff08;SSA&#xff09;的无人机路径规划&#xff08;Matlab&#xff09; 一、算法背景与核心思想 麻雀搜索算法&#xff08;Sparrow Search Algorithm, SSA&#xff09;是一种受麻雀群体觅食行为启发的元启发式算法&#xff0…...

2020CVPR-SiamBAN:用于视觉跟踪的Siamese框自适应网络

原文标题&#xff1a;Siamese Box Adaptive Network for Visual Tracking 中文标题&#xff1a;用于视觉跟踪的Siamese框自适应网络 代码地址&#xff1a; GitHub - hqucv/siamban: Siamese Box Adaptive Network for Visual Tracking Abstract 大多数现有的跟踪器通常依靠多尺…...

带你从入门到精通——自然语言处理(五. 自注意力机制和transformer的输入部分)

建议先阅读我之前的博客&#xff0c;掌握一定的自然语言处理前置知识后再阅读本文&#xff0c;链接如下&#xff1a; 带你从入门到精通——自然语言处理&#xff08;一. 文本的基本预处理方法和张量表示&#xff09;-CSDN博客 带你从入门到精通——自然语言处理&#xff08;二…...

MySql自动安装脚本

一、脚本安装流程 1. 添加MySQL的Repository 使用wget命令从MySQL官方网站下载Yum Repository的RPM包。使用rpm -ivh命令安装下载的RPM包&#xff0c;以添加MySQL的Yum Repository。 2. 安装mysql-community-server 使用yum install -y mysql-community-server --nogpgchec…...

3.9【Q】csd

在计算机存储领域&#xff0c;CSD是什么&#xff1f; 基于CXL™-Type3 实现内存池化 CPU访问内存的瓶颈是什么&#xff1f;具体矛盾是什么&#xff1f; 计算型存储-2&#xff1a;标准、API实现 NUMA是什么&#xff1f;详细解释一下它的核心思想&#xff1f;...

Qt常用控件之表格QTableWidget

表格QTableWidget QTableWidget 是一个表格控件&#xff0c;行和列交汇形成的每个单元格&#xff0c;是一个 QTableWidgetItem 对象。 1. QTableWidget属性 QTableWidget 的属性只有两个&#xff1a; 属性说明rowCount当前行的个数。columnCount当前列的个数。 2. QTableW…...

数据库批处理

数据库批处理是一种处理数据的方法&#xff0c;通常用于对大量数据进行一次性操作。批处理可以有效地减少数据库操作的次数&#xff0c;提高数据处理的效率。在数据库中&#xff0c;批处理通常通过编写批处理脚本或使用相应的工具来实现。 一般情况下&#xff0c;数据库批处理…...

Flask 框架简介

Flask 框架简介 Flask 框架简介 Flask 框架简介 Flask 是一个 Python 微型网页开发框架。微型指明了 Flash 的核心是轻量级的&#xff0c;但是可以灵活扩展。下面的简单的例子要和一个数据库系统交互。Django附带了与最常见的数据库交互所需的库。另一方面&#xff0c;Flask允…...