Linux线程_线程互斥_线程同步
一.线程互斥
1.进程线程间的互斥相关概念
临界资源:多线程执行流共享的资源就叫做临界资源
临界区:每个线程内部,访问临界资源的代码,就叫做临界区
互斥:任何时刻,互斥保证有且只有一个执行流进入临界区,访问临界资源,通常对临界资源起保护作用
原子性:不会被任何调度机制打断的操作,该操作只有两态,要么完成,要么未完成。
有多个线程对临界资源num=10000进行--操作 直到num==0。如果不进行保护,num为什么会<0?
1.num--操作并不是原子性的,实际上分为三部 1.把数据从内存存入CPU的寄存器 2.数据-- 3.再把寄存器的数据写回内存
2.if(num>0) 也不是原子性的,分为读取和比较操作。如果刚读取完num==1,条件符合,线程1进入,还没进行--就被切换,线程2读取 条件仍符合,线程2进入。这样就可能会放入多个线程进入。
3.让线程尽可能的切换
线程什么时候会被切换?
1.时间片用完
2.高优先级线程抢占当前线程3.当前线程进入阻塞状态(等待 I/O 或资源)
sleep会让当前线程进入等待队列,并切换其它线程进行调度。等到sleep结束,从内核态转为用户态,会检测时间片是否结束,结束进行切换其它线程。
因此根本原因就在于if(num>0)不是原子性的,让多个线程进入判断内部,导致num<0
2.互斥锁函数
解决上面的问题,就要完成在判断内部也就是临界区内只有一个线程执行。
对临界区进行加锁就可以保证临界区内只有一个线程执行。
下面我们看一下锁的用法
1.PTHREAD_MUTEX_INITIALIZER宏初始化
有两种初始化锁的方法,这是用宏对锁静态初始化。
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER
定义的时候就完成初始化,通常用于声明全局或静态的互斥锁。
初始化好锁后,怎么用呢?
1.进入临界区前 加锁
pthread_mutex_lock()
#include <pthread.h> int pthread_mutex_lock(pthread_mutex_t *mutex);
mutex指向要进行加锁操作的锁 成功返回0 失败返回错误码
2.出临界区后 解锁
pthread_mutex_unlock()
int pthread_mutex_unlock(pthread_mutex_t *mutex);
mutex指向要进行解锁操作的锁 成功返回0 失败返回错误码
2.pthread_mutex_init()函数初始化
先定义锁,再用函数初始化。适用于局部变量、需要在运行时初始化的互斥锁。
可以传递锁的属性。需要在使用完后调用 pthread_mutex_destroy 销毁。
#include <pthread.h>pthread_mutex_t mutex; // 声明但不初始化void *thread_func(void *arg) {pthread_mutex_lock(&mutex); // 加锁// 访问共享资源pthread_mutex_unlock(&mutex); // 解锁 }int main() {pthread_t thread1, thread2;// 动态初始化互斥锁pthread_mutex_init(&mutex, NULL); // 初始化互斥锁pthread_create(&thread1, NULL, thread_func, NULL);pthread_create(&thread2, NULL, thread_func, NULL);pthread_join(thread1, NULL);pthread_join(thread2, NULL);pthread_mutex_destroy(&mutex); // 销毁互斥锁return 0; }
pthread_mutex_init()
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
mutex 指向要初始化的锁 attr锁的属性
pthread_mutex_destroy()
int pthread_mutex_destroy(pthread_mutex_t *mutex);
mutex指向要销毁的锁
每次进出临界区的时候都要进行加锁 解锁操作,有什么办法可以自动对临界区进行加锁 解锁?
#pragma once #include <iostream> #include <pthread.h>namespace LockModule {class Mutex{public:Mutex(const Mutex&) = delete;const Mutex& operator = (const Mutex&) = delete;Mutex(){int n = ::pthread_mutex_init(&_lock, nullptr);(void)n;}~Mutex(){int n = ::pthread_mutex_destroy(&_lock);(void)n;}void Lock(){int n = ::pthread_mutex_lock(&_lock);(void)n;}void Unlock(){int n = ::pthread_mutex_unlock(&_lock);(void)n;}private:pthread_mutex_t _lock;};class LockGuard{public:LockGuard(Mutex &mtx):_mtx(mtx){_mtx.Lock();}~LockGuard(){_mtx.Unlock();}private:Mutex &_mtx;}; }
定义一个Mutex类,它的构造函数就是初始化成员变量_block锁,析构函数是销毁锁。有解锁 加锁的函数。再定义一个以Mutex类对象为成员变量的LockGuard类,构造函数进行加锁操作,析构函数进行解锁操作。这样创建一个LockGuard对象就完成了加锁,销毁时就完成了解锁操作。
我们把临界区单独放在一个作用域里面,在临界区的作用域里面一开始创建LockGuard对象自动调用构造函数完成加锁,等到出作用域自动调用析构函数,完成解锁。
3.互斥量实现原理
pthread_mutex_lock()到底怎么完成只让一个线程进入临界区,实现互斥操作的呢?
为了实现互斥锁操作,大多数体系结构都提供了 swap 或 exchange 指令,该指令 的作用是把寄存器和内存单元的数据相交换,由于只有一条指令,保证了原子性,即使 是多处理器平台,访问内存的 总线周期也有先后,一个处理器上的交换指令执行时另 一个处理器的交换指令只能等待总线周期。 现在我们把 lock 和 unlock 的伪代码改一下。
在内存中互斥锁mutex可以理解成一个计数器,默认为1,代表没有线程在临界区,可以进入。为0代表有线程在临界区不能进入。
进入lock函数:
1.move $0 %al 把0值写入寄存器
2.xchgb 把寄存器数据0和内存mutex数据交换(原子性)
3.如果寄存器内数据>0 代表没有线程在临界区,可以进入。
==0 有线程在临界区,进入等待队列。等待结束后再重新执行lock函数 直到>0返回
unlock函数:
把1写入mutex中 (原子性),退出临界区,表示允许线程进入临界区。
二.线程同步
1.同步概念
互斥可以保证只有一个线程进入临界区访问临界资源,但多个线程竞争同一份临界资源,如果有一个线程总是能访问到,而其它线程一直在等待,这就造成了饥饿问题。怎么才能解决线程间资源的竞争呢?
同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从而有效避免饥饿问题,叫做同步。
同步的机制有 互斥锁(确保每次只有一个线程能访问临界区,防止并发访问同一资源)
条件变量 (让线程在某个条件满足之前挂起,直到其他线程通知它继续执行)
信号量 (用于控制访问共享资源的线程数量)
条件变量可以协调线程的执行顺序。
2.条件变量函数
初始化
1.PTHREAD_COND_INITIALIZER宏
一般用于初始化全局条件变量
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
2.int pthread_cond_init()
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
cond:指向要初始化的条件变量的指针。
attr:用于设置条件变量的属性,一般传入 NULL,表示使用默认属性。
返回值:成功时返回 0,失败时返回错误码。
pthread_cond_destroy()销毁
int pthread_cond_destroy(pthread_cond_t *cond);
pthread_cond_wait() 等待条件变量
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
cond:条件变量。
mutex:互斥锁,在调用 pthread_cond_wait 时必须持有该锁。调用 wait 会解锁,并使当前线程阻塞,直到条件变量被通知。
返回值:成功时返回 0,失败时返回错误码。
注意:pthread_cond_wait 会解锁并使当前线程阻塞,直到条件变量收到通知,线程被唤醒后,重新加锁。
pthread_cond_signal() 通知一个线程
int pthread_cond_signal(pthread_cond_t *cond);
cond:条件变量,通知一个等待该条件变量的线程。
返回值:成功时返回 0,失败时返回错误码。
pthread_cond_broadcast() 通知所有线程
int pthread_cond_broadcast(pthread_cond_t *cond);
cond:条件变量,通知所有等待该条件变量的线程。
返回值:成功时返回 0,失败时返回错误码。
3.生产消费者模型
1.什么是生产消费者模型
互斥锁和条件变量怎么搭配使用呢?
先讲一个场景,生产消费者模型。
有多个工厂向超市放资源,超市存入资源且大小有限,消费者从超市拿资源。
可以理解为有多个线程向临界区存入资源,有多个线程从临界区取资源。在此过程中要保证临界区的安全,还有保证高效。
在此场景中有三种关系:
1.生产者和生产者 两个生产者可以同时进入超市吗?不能,如果超市刚好差一个资源就满,那么就不能保证资源安全。
所以生产者和生产者关系为:互斥
2.消费者和消费者 两个消费者可以同时进入超市吗?不能,超市有只有一个资源的情况
所以消费者和消费者关系为:互斥
3.消费者和生产者 一个消费者和一个生产者可以同时进入吗?不能,消费者在取资源时怎么知道生产者有没有放资源,消费者先取发现没有,回去说里面没有资源,生产者再放,回去说里面有资源,造成二义性。
所以消费者和生产者关系为:互斥
消费者发现超市没有资源,就回去,等一段时间再访问有没有资源,不停循环访问。这样虽然合理,但不高效。如果能什么时候有资源了,就通知一声消费者再让它过来就可以了,
那么谁知道什么时候有资源呢?生产者,因为相互互斥,等生产者出来的时候一定有资源,让生产者通知消费者取资源就可以了。反过来,消费者也知道什么时候资源没满,消费者出来的时候,再通知生产者存入资源就可以了。
所以消费者和生产者关系为:互斥+同步
下面我们用代码模拟上述场景,多个线程分别当作生产者 消费者,用阻塞队列当作有资源上线的超市。(当队列为空时,消费者线程会被阻塞,直到队列中有元素可以消费;当队列满时,生产者线程会被阻塞,直到队列中有空位可以插入新的元素。阻塞队列常用于多线程环境中的生产者-消费者问题等场景。)
2.代码模拟
#pragma once#include<iostream>
#include<cstdio>
#include<queue>
#include "Mutex.hpp"
#include "Cond.hpp"using namespace LockModule;
using namespace CondModule;namespace BlockQueueModule
{static const int gcap = 10;template<typename T>class BlockQueue{private:bool IsFull(){return _cap==_q.size();}bool IsEmpty(){return _q.empty();}public:BlockQueue(int cap=gcap):_cap(cap){// pthread_mutex_init(&_mutex,nullptr);// pthread_cond_init(&_p_cond,nullptr);// pthread_cond_init(&_c_cond,nullptr);}void Pop(int*data){//pthread_mutex_lock(&_mutex);LockGuard lockguard(_mutex);//1.队列不能为空while(IsEmpty()){_c_nums++;//pthread_cond_wait(&_c_cond,&_mutex);_c_cond.Wait(_mutex);_c_nums--;}*data=_q.front();_q.pop();//if(_p_nums) pthread_cond_signal(&_p_cond);if(_p_nums) _c_cond.Notify();//pthread_mutex_unlock(&_mutex);}void Equeue(const int&data) //生产者{//pthread_mutex_lock(&_mutex);LockGuard lockguard(_mutex);//初始化自动上锁 出作用域解锁//1.放入数据前队列不能为满while(IsFull()){//2.为满就让该线程释放锁 进入等待队列_p_nums++;// 等待生产者线程+1//pthread_cond_wait(&_p_cond,&_mutex);//wait的时候 有锁的话 会导致消费线程申请不到锁 导致一直在等待_p_cond.Wait(_mutex);_p_nums--;//3.等待结束唤醒线程 并申请锁(因为在临界区内,pthread_cond_wait会自动申请锁)}//4.到此时肯定未满 生产者存入数据_q.push(data);//5.此时肯定有数据//if(_c_nums) pthread_cond_signal(&_c_cond); //有等待的消费者线程就唤醒一个if(_c_nums) _p_cond.Notify();//6.唤醒线程要在解锁前还是解锁后?//signal通知线程 线程被唤醒后还要申请到锁才能继续执行//(1)在解锁前唤醒它 它申请不到锁 就会阻塞在申请锁的队列中 直到申请到锁//(2)如果被其它进程申请到了锁 就继续阻塞在申请锁的队列中 //7.如果生产者只生成了1个资源,但broadcast()唤醒了等待队列的所有线程会怎么样?//会发生伪唤醒。第一个申请到锁的线程获取了资源。现在没有资源了,可是第二个申请到锁的线程还是会在临界区内继续执行 //解决方法:if()改为while()判断 在线程被唤醒后,重新检查条件是否满足,并在不满足时重新进入等待状态。//(即重新看是否满足while的判断,满足就重新进入等待队列,不满足退出while循环)//pthread_mutex_unlock(&_mutex);}~BlockQueue(){// pthread_mutex_destroy(&_mutex);// pthread_cond_destroy(&_p_cond);// pthread_cond_destroy(&_c_cond);}private:std::queue<T> _q;//队列int _cap; //队列数据上限Mutex _mutex; //互斥Cond _p_cond; //生产者条件变量Cond _c_cond; //消费者条件变量int _c_nums=0; //等待的消费者线程int _p_nums=0; //等待的生产者线程};
}
对条件变量的封装
#pragma once#include "Mutex.hpp"using namespace LockModule;namespace CondModule
{class Cond{public:Cond(){int n=pthread_cond_init(&_cond,nullptr);(void)n;}void Wait(Mutex&mutex){int n=pthread_cond_wait(&_cond,mutex.LockPtr());(void)n;}void Notify(){int n=pthread_cond_signal(&_cond);(void)n;}void NotifyAll(){int n=pthread_cond_broadcast(&_cond);(void)n;}~Cond(){int n=pthread_cond_destroy(&_cond);(void)n;}private:pthread_cond_t _cond;};
}
对锁的封装
#pragma once
#include <iostream>
#include <pthread.h>namespace LockModule
{class Mutex{public:Mutex(const Mutex&) = delete;const Mutex& operator = (const Mutex&) = delete;Mutex(){int n = ::pthread_mutex_init(&_lock, nullptr);(void)n;}~Mutex(){int n = ::pthread_mutex_destroy(&_lock);(void)n;}void Lock(){int n = ::pthread_mutex_lock(&_lock);(void)n;}pthread_mutex_t *LockPtr(){return &_lock;}void Unlock(){int n = ::pthread_mutex_unlock(&_lock);(void)n;}private:pthread_mutex_t _lock;};class LockGuard{public:LockGuard(Mutex &mtx):_mtx(mtx){_mtx.Lock();}~LockGuard(){_mtx.Unlock();}private:Mutex &_mtx;};
}
上层接口
#include"BlcokQueue.hpp"
#include<pthread.h>
#include<unistd.h>using namespace BlockQueueModule;void* Consumer(void*args)
{BlockQueue<int>*bq=static_cast<BlockQueue<int>*>(args);int data;while (true){sleep(2);//1.从队列中获取数据bq->Pop(&data);//2.处理数据printf("消费者获取数据:%d\n",data);}}void* Productor(void*args)
{BlockQueue<int>*bq=static_cast<BlockQueue<int>*>(args);//1.从外部获取数据int data=10;while(true){//2.把数据输入队列中bq->Equeue(data);printf("生产者存入数据:%d\n",data);data++;}
}
int main()
{BlockQueue<int>* bq=new(BlockQueue<int>);pthread_t c,p;pthread_create(&c,nullptr,Consumer,(void*)bq);pthread_create(&p,nullptr,Productor,(void*)bq);pthread_join(p,nullptr);pthread_join(c,nullptr);delete bq;}
3.生产消费者模型高效在哪里?
生产消费者模型,三种关系生产者和生产者 消费者和消费者 生产者和消费者都是互斥的,在临界区内都是串行的,有一个线程在内,其它线程都不能进来,怎么就高效了呢?
想一想,当其中一个线程在临界区内,其它线程呢?
1.生产者在从外部获取数据,不需要等待消费者处理完数据。消费者在处理数据,不需要等待生产者生成数据。
通过这种方式,生产者和消费者可以并行运行,避免了阻塞和等待,从而提高了资源的利用率。2.临界区可以当作缓冲区,调节生产与消费的速度。
如果生产者的生产速度快于消费者的消费速度,缓冲区会存储数据,生产者可以继续生产而不会被阻塞。
如果消费者的消费速度快于生产者的生产速度,缓冲区中的数据会被快速消费,生产者有更多的时间来生产新数据。
相关文章:
Linux线程_线程互斥_线程同步
一.线程互斥 1.进程线程间的互斥相关概念 临界资源:多线程执行流共享的资源就叫做临界资源临界区:每个线程内部,访问临界资源的代码,就叫做临界区互斥:任何时刻,互斥保证有且只有一个执行流进入临界区&…...
【Spiffo】环境配置:VScode+Windows开发环境
摘要: 在Linux下直接开发有时候不习惯快捷键和操作逻辑,用Windows的话其插件和工具都更齐全、方便,所以配置一个Windows的开发环境能一定程度提升效率。 思路: 自己本地网络内远程连接自己的虚拟机(假定用的是虚拟机…...
DevExpress控件 基本使用
DevExpress控件 一、DevExpress简介 1、所有编辑器的公共功能 全部都可以绑定数据; 全部都可以独立使用或用于由 Developer Express 提供的容器控件 (XtraGrid、XtraVerticalGrid、XtraTreeList 和 XtraBars) 内的内置编辑; 全部都使用相同的样式、外…...
设计模式——装饰器模式
装饰器模式是结构型设计模式,在Python中有一个非常著名的装饰器wrapper,它的实现方法就是使用了该设计模式,装饰器可以修饰类也可以修饰函数。 从类的设计上说,他的本质是在不定义子类的情况下动态的给对象添加一些额外的功能。举…...
【编程题目】列表、元组及集合
一.列表的题目 题目1:列表反转与排序 描述:给定一个整数列表,首先反转该列表,然后对其进行升序排序。最后输出处理后的列表。输入:一个整数列表,例如 [3, 1, 4, 1, 5, 9]输出:处理后的列表,例如 [1, 1, 3, 4, 5, 9]示例:input_list = [3, 1, 4, 1, 5, 9] # 你的代码 …...
【大数据学习 | Spark-Core】RDD的缓存(cache and checkpoint)
1. 单应用缓存:cache 1.1 cache算子 cache算子能够缓存中间结果数据到各个executor中,后续的任务如果需要这部分数据就可以直接使用避免大量的重复执行和运算。 rdd 存储级别中默认使用的算子cache算子,cache算子的底层调用的是persist算子…...
自主研发,基于PHP+ vue2+element+ laravel8+ mysql5.7+ vscode开发的不良事件管理系统源码,不良事件管理系统源码
不良事件上报系统源码,不良事件管理系统源码,PHP源码 不良事件上报系统通过 “事前的人员知识培训管理和制度落地促进”、“事中的事件上报和跟进处理”、 以及 “事后的原因分析和工作持续优化”,结合预存上百套已正在使用的模板࿰…...
哈希表理解与底层模拟实现
内容摘要 本文内容包括红黑树和哈希表的性能比较逻辑分析及实现、哈希表的概念、哈希表映射关系建立的最常用的两种方法直接地址法和除留余数法介绍、介绍了哈希冲突的原因以及解决解决哈希冲突的方法、负载因子的概念、哈希表的扩容、开散列实现哈希表的思路及代码实现、闭散列…...
docker compose的安装和使用
1. Docker Compose 简介 Docker Compose 是一个工具,用于定义和运行多容器的 Docker 应用。通过编写一个 docker-compose.yml 文件,可以一次性启动所有容器,并且方便管理容器之间的依赖。 2. 安装 Docker Compose 前提条件 确保已安装 Do…...
17种Kubernetes安全检测工具详解
随着Kubernetes的广泛应用,确保其安全性就显得尤为重要。好在现有很多优秀的安全检测工具,可以帮助我们发现和修复Kubernetes集群中的安全隐患。本文将全面介绍17种常用的Kubernetes安全检测工具。 Kube-benchKube-hunterKubesec.ioTrivyKube-auditKube-secKube-vulnkube-scana…...
Python遥感开发之CGCS2000转换WGS84地理坐标系
Python遥感开发之CGCS2000转换WGS84地理坐标系 1 CGC2000坐标系介绍2 WGS84地理坐标系介绍3 代码实现CGCS2000转换WGS84地理坐标系 前言:主要借助pyproj实现从CGCS2000高斯-克吕格3度带(EPSG:4547)转换到WGS84地理坐标系(EPSG:432…...
FAX动作文件优化脚本(MAX清理多余关键帧插件)
大较好,为大家介绍一个节省FBX容量的插件!只保留有用的动画轴向,其他不参与动画运动的清除! 一.插件目的:: 1.我们使用的U3D引擎产生的游戏资源包容量太大,故全方位优化动画资源; 2.在max曲线编辑器内,点取轴向太过麻烦,费事,直观清除帧大大提高效率。 如: 二:…...
Springboot集成ElasticSearch实现minio文件内容全文检索
一、docker安装Elasticsearch (1)springboot和Elasticsearch的版本对应关系如下,请看版本对应: 注意安装对应版本,否则可能会出现一些未知的错误。 (2)拉取镜像 docker pull elasticsearch:7…...
Python 中的 | 符号
Python 中的 | 符号 正文用法 1用法2 正文 今天遇到了一个符号 |,本文将对符号 | 的意思进行说明。 x: int 1 print(x) # 1上述代码中,:int 表示的是注释内容,这个在 python 中的注释 一文中我们已经进行了说明。 用法 1 有些时候我们会…...
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务 IDS入侵检测系统 Intrusion Detection System 安全检测系统,通过监控网络流量、系统日志等信息,来检测系统中的安全漏洞、异常行为和入侵行为。 分为&am…...
记录elasticsearch-analysis-dynamic-synonym从8.15.0升级到8.16.0所遇到的问题
记录elasticsearch-analysis-dynamic-synonym从8.15.0升级到8.16.0所遇到的问题 一、打包步骤 步骤一、linux系统下执行elasticsearch-module中的build.sh脚本 步骤二、maven环境下elasticsearch-cluster-runner执行maven install命令安装到本地maven仓库。 步骤三、修改版…...
IDEA怎么定位java类所用maven依赖版本及引用位置
在实际开发中,我们可能会遇到需要搞清楚代码所用依赖版本号及引用位置的场景,便于排查问题,怎么通过IDEA实现呢? 可以在IDEA中打开项目,右键点击maven的pom.xml文件,或者在maven窗口下选中项目,…...
react native 安装好apk后无法打开
react native 打包好apk安装完成,没有打开app按钮, 在AndroidManifest.xml中 <intent-filter><action android:name"android.intent.action.MAIN" /><category android:name"android.intent.category.LAUNCHER" /&…...
HTML5 SVG
HTML5 SVG SVG(Scalable Vector Graphics)是一种基于XML的图像格式,用于在网页上创建矢量图形。与传统的位图图像(如PNG和JPEG)不同,SVG图像可以无限放大而不失真,因为它们是由直线和曲线定义的数学路径,而不是像素点。HTML5支持直接在网页中嵌入SVG,使得网页设计更加…...
【LeetCode每日一题】——485.最大连续 1 的个数
文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时空频度】九【代码实现】十【提交结果】 一【题目类别】 数组 二【题目难度】 LeetCode 三【题目编号】 485.最大连续 1 的个数 四【题目描述】 给定…...
Python语言就业方向有哪些?
Python语言的就业方向非常广泛,涵盖了多个领域和职位,主要包括: Web开发 Python在Web开发领域有着广泛的应用,特别是通过框架如Django、Flask等。Python可以帮助开发者快速搭建网站,与各种前端技术集成,从而…...
SpringSecurity创建一个简单的自定义表单的认证应用
1、SpringSecurity 自定义表单 在 Spring Security 中创建自定义表单认证应用是一个常见的需求,特别是在需要自定义登录页面、认证逻辑或添加额外的表单字段时。以下是一个详细的步骤指南,帮助你创建一个自定义表单认证应用。 2、基于 SpringSecurity 的…...
wpf 事件转命令的方式
1,方式1 <StackPanel Background"Transparent"><StackPanel.InputBindings><KeyBinding Command"{Binding ChangeColorCommand}"CommandParameter"{Binding ElementNamecolorPicker, PathSelectedItem}"Key"{Bi…...
Docker 容器的初始化设置
虽然现在Conntainerd 大有取代Docker作为容器运行时的趋势,但是docker还是有自己的优势在。尤其是对于开发者来讲,使用Docker 比使用 containerd 方便很多,尤其是在Docker Desktop等工具的加持下。 本文主要面向Docker的初、中级学者…...
python里的数据结构
列表(List) 定义和特点: 列表是一种有序的可变序列,可包含不同类型的元素,如整数、字符串、列表等。可以通过索引访问和修改元素,索引从 0 开始。代码示例: my_list [1, 2, apple, [4, 5]] pr…...
Ros Noetic 20.04 跑通mpc_ros包保姆级教程
前言: 本文将简述mpc_ros包在noetic20.04中的安装,mpc是 一种跟踪、MPC_ROS 是一个基于ROS(Robot Operating System)的模型预测控制(Model Predictive Control,MPC)库。该项目旨在为机器人控制提供一个灵活且高效的MPC实现,使得开发者能够在ROS环境中轻松集成和使用MPC…...
MySQL 没有数据闪回?看 zCloud 如何补齐MySQL数据恢复能力
ENMOTECH 上一篇文章为大家介绍了某金融科技企业通过 zCloud 多元数据库智能管理平台的告警中心“警警”有条地管理告警并进行敏捷处置的实践案例。本篇跟大家继续分享该案例客户如何利用 zCloud 备份恢复模块下的Binlog解析功能补齐 MySQL 数据恢复能力,让运维人员…...
k8s集群加入node节点为ubuntu 22.04
文章目录 1.环境准备1.1 关闭无用服务1.2 环境和网络1.3 apt源1.4 系统优化 2. 装containerd3. 接入k8s集群3.1 kubelet、kubeadm、kubectl安装3.2 缺少一个镜像3.3 接入k8s集群 4. 一些相关问题 1.环境准备 rootcto-gpu-pro-n01:~# lsb_release -a No LSB modules are availa…...
提取图片高频信息
提取图片高频信息 示例-输入: 示例-输出: 代码实现: import cv2 import numpy as npdef edge_calc(image):src cv2.GaussianBlur(image, (3, 3), 0)ddepth cv2.CV_16Sgray cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)grad_x cv2.Scharr(g…...
向量数据库FAISS之四:向量检索和 FAISS
来自 YouTube 1.相似度搜索的传统方法(Jaccard, w-shingling, Levenshtein) 1.Jaccard 距离 公式 Jaccard ( A , B ) 1 − ∣ A ∩ B ∣ ∣ A ∪ B ∣ \text{Jaccard}(A, B) 1 - \frac{|A \cap B|}{|A \cup B|} Jaccard(A,B)1−∣A∪B∣∣A∩B∣ 其中, A 和 …...
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
目录 安装包 flume的部署 负载均衡测试 故障恢复 安装包 在这里给大家准备好了flume的安装包 通过网盘分享的文件:apache-flume-1.9.0-bin.tar.gz 链接: https://pan.baidu.com/s/1DXMA4PxdDtUQeMB4J62xoQ 提取码: euz7 --来自百度网盘超级会员v4的分享 ----…...
行列式的理解与计算:线性代数中的核心概念
开发领域:前端开发 | AI 应用 | Web3D | 元宇宙 技术栈:JavaScript、React、ThreeJs、WebGL、Go 经验经验:6 年 前端开发经验,专注于图形渲染和 AI 技术 开源项目:github 简智未来、数字孪生引擎、前端面试题 大家好&a…...
DimensionX:单图生成任意的3d/4d视图
DimensionX:单图生成任意的3d/4d视图 通俗易懂的来说 在我们的方法中,关键是如何从一张图片生成动态的3D和4D场景。我们使用一个叫做ST-Director的工具,它可以分开处理空间(3D)和时间(4D)两个方面。想象一…...
k8s上面的Redis集群链接不上master的解决办法
问题描述 之前在k8s上面部署了一台node,然后创建了6个redis的pod,构建了一个redis的集群,正常运行。 最近添加了一台slave node,然后把其中的几个redis的pod调度到了slave node上面,结果集群就起不来了,…...
芯片之殇——“零日漏洞”(文后附高通64款存在漏洞的芯片型号)
芯片之殇——“零日漏洞”(文后附高通64款存在漏洞的芯片型号) 本期是平台君和您分享的第113期内容 前一段时间,高通公司(Qualcomm)发布安全警告称,提供的60多款芯片潜在严重的“零日漏洞”,芯片安全再一次暴露在大众视野。 那什么是“零日漏洞”?平台君从网上找了一段…...
《线性代数的本质》
之前收藏的一门课,刚好期末复习,顺便看一看哈哈 课程链接:【线性代数的本质】合集-转载于3Blue1Brown官方双语】 向量究竟是什么 线性代数中最基础、最根源的组成部分就是向量,需要先明白什么是向量 不同专业对向量的看法 物理专…...
计算机视觉 1-8章 (硕士)
文章目录 零、前言1.先行课程:python、深度学习、数字图像处理2.查文献3.环境安装 第一章:概论1.计算机视觉的概念2.机器学习 第二章:图像处理相关基础1.图像的概念2.图像处理3.滤波器4.卷积神经网络CNN5.图像的多层表示:图像金字…...
SpringMVC
七、SpringMVC (1)SpringMVC简介 SpringMVC概述 SpringMVC技术与Servlet技术功能等同,均属于web层开发技术,web程序大都基于三层架构实现 如果所有的处理都交给Servlet来处理的话,所有的东西都耦合在一起,…...
使用llama.cpp进行量化和部署
git clone https://github.com/ggerganov/llama.cpp cd llama.cpp 🖥️ CPU 版本 cmake -B build_cpu cmake --build build_cpu --config Release 🖥️ CUDA 版本 cmake -B build_cuda -DLLAMA_CUDAON cmake --build build_cuda --config Release -j …...
iOS构建版本以及Hbuilder打iOS的ipa包全流程
目录 Hbuilder打ipa包 打包之前进行应用配置 应用版本号设置 使用广告标识设置 iOS-云打包 下载并转移安装包 使用Transporter提交版本 应用简介 下载应用 账号登录 提交安装包到apple store connect 在apple开发者平台上确认 总结 本篇文章详细的介绍了使用Hbuil…...
DB-GPT V0.6.2 版本更新:牵手libro社区、GraphRAG图谱构建能力增强等
DB-GPT V0.6.2版本现已上线,快速预览新特性: 新特性 1、DB-GPT 社区和 libro 社区共同发布 AWEL Notebook 功能 libro:灵活定制、轻松集成的 Notebook 产品方案。 社区地址:https://github.com/difizen/libro 使用教程…...
Chrome 浏览器 131 版本新特性
Chrome 浏览器 131 版本新特性 一、Chrome 浏览器 131 版本更新 1. 在 iOS 上使用 Google Lens 搜索 自 Chrome 126 版本以来,用户可以通过 Google Lens 搜索屏幕上看到的任何图片或文字。 要使用此功能,请访问网站,并点击聚焦时出现在地…...
数据结构初识
目录 1.初识 2.时间复杂度 常见时间复杂度举例: 3.空间复杂度 4.包装类&简单认识泛型 4.1装箱和拆箱 5.泛型 6.泛型的上界 7.泛型方法 8.List接口 1.初识 1.多画图 2.多思考 3.多写代码 4.多做题 牛客网-题库/在线编程/剑指offer 算法篇:…...
[ 应急响应进阶篇-2 ] Linux创建后门并进行应急处置-1:超级用户帐号后门
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...
设计模式:4、命令模式(双重委托)
目录 0、定义 1、命令模式包括四种角色 2、命令模式的UML类图 3、代码示例 0、定义 将一个请求封装为一个对象,从而使用户可用不同的请求对客户进行参数化;对请求排队或记录请求日志,以及支持可撤销的操作。 1、命令模式包括四种角色 接…...
第27天 安全开发-PHP应用TP 框架路由访问对象操作内置过滤绕过核心漏洞
时间轴 演示案例 TP 框架-开发-配置架构&路由&MVC 模型 TP 框架-安全-不安全写法&版本过滤绕过 TP 框架-开发-配置架构&路由&MVC 模型 参考: https://www.kancloud.cn/manual/thinkphp5_1 1、配置架构-导入使用 去thinkphp官网可以看到&…...
[数组双指针] 0167. 两数之和 II - 输入有序数组
文章目录 1. 题目链接2. 题目大意3. 示例4. 解题思路5. 参考代码 1. 题目链接 167. 两数之和 II - 输入有序数组 - 力扣(LeetCode) 2. 题目大意 描述:给定一个下标从 1 开始计数、升序排列的整数数组:numbers 和一个目标值 targ…...
常用数据结构详解
文章目录 线性数据结构稀疏数组链表单向链表双向链表约瑟夫问题 栈栈实现中缀表达式栈实现后缀表达式中缀表达式转后缀表达式 队列哈希表 非线性数据结构二叉树二叉树的遍历及查找二叉树的删除顺序存储二叉树线索化二叉树 哈夫曼树二叉排序树平衡二叉树多路查找树2-3树B树B树B*…...
css iframe标签使用
<iframe> 标签用于在网页中嵌入另一个 HTML 页面。它非常灵活,可用于嵌入内容,比如其他网站、视频、地图等。以下是有关 <iframe> 的详细介绍及使用方法: 基本语法 <iframe src"URL" width"宽度" height…...
NVR管理平台EasyNVR多品牌NVR管理工具的流媒体视频融合与汇聚管理方案
随着信息技术的飞速发展,视频监控已经成为现代社会安全管理和业务运营不可或缺的一部分。无论是智慧城市、智能交通、还是大型企业、校园安防,视频监控系统的应用都日益广泛。NVR管理平台EasyNVR,作为功能强大的流媒体服务器软件,…...