Linux线程
一、线程的使用
线程创建
函数原型及头文件
#include <pthread.h>
int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg);
参数:
- tidp:当pthread_create成功返回时,由tidp指向的内存单元被设置为新创建线程的线程ID。
- attr:一般设为NULL。attr参数用于定制各种不同的线程属性,暂可以把它设置为NULL,以创建默认属性的线程。
(*start_rtn)(void *):
新创建的线程的入口地址。新创建的线程从start_rtn函数的地址开始运行,该函数只有一个无类型指针参数arg。- arg:向start_rtn函数传递的参数。如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,然后把这个结构的地址作为arg参数传入。(指针,输入方式是地址,同时要注意是void *型)
返回值:若成功返回0,否则返回错误编号。
线程退出
单个线程可以通过以下三种方式退出,在不终止整个进程的情况下停止它的控制流:
1)线程只是从启动例程中返回,返回值是线程的退出码。
2)线程可以被同一进程中的其他线程取消。
3)线程调用pthread_exit。
函数原型及头文件
#include <pthread.h>
int pthread_exit(void *rval_ptr);
参数:rval_ptr:一个无类型指针,与传给启动例程的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。
线程等待
调用这个函数的线程将一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果例程只是从它的启动例程返回i,rval_ptr将包含返回码。如果线程被取消,由rval_ptr指定的内存单元就置为PTHREAD_CANCELED。
可以通过调用pthread_join自动把线程置于分离状态,这样资源就可以恢复。如果线程已经处于分离状态,pthread_join调用就会失败,返回EINVAL。
函数原型及头文件
#include <pthread.h>
int pthread_join(pthread_t thread, void **rval_ptr);
参数:
- thread:线程名
- **rval_ptr:线程的返回值。如果对线程的返回值不感兴趣,可以把rval_ptr置为NULL。在这种情况下,调用pthread_join函数将等待指定的线程终止,但并不获得线程的终止状态。
返回值:若成功返回0,否则返回错误编号。
线程脱离
函数原型及头文件
#include <pthread.h>
int pthread_detach(pthread_t thread);
参数解读
一个线程或者是可汇合(joinable,默认值),或者是脱离的(detached)。当一个可汇合的线程终止时,它的线程ID和退出状态将留存到另一个线程对它调用pthread_join。脱离的线程却像守护进程,当它们终止时,所有相关的资源都被释放,我们不能等待它们终止。如果一个线程需要知道另一线程什么时候终止,那就最好保持第二个线程的可汇合状态。
pthread_detach函数把指定的线程转变为脱离状态。
返回值:若成功返回0,否则返回错误编号。
线程ID获取
函数原型及头文件
#include <pthread.h>
pthread_t pthread_self(void);
返回值:调用线程的ID。
示例代码使用
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_fun(void* arg)
{int num = *(int*)arg;printf("num = %d\n",num);printf("这就是子线程\n");sleep(3);pthread_exit("hello");
}int main()
{pthread_t tid;int arg = 10;void* retv;int ret = pthread_create(&tid, NULL, thread_fun, (void*)&arg);if(ret == 0){printf("create succes\n");}pthread_join(tid, &retv);printf("子线程结束了 %s\n",(char*)retv);while(1){}return 0;
}/* 传输数字 */
static int ret = 10;//传出数据前面一定要加static!!!
pthread_exit((void *)&ret);int *pret;//用于存放线程退出时传出的数据
pthread_join(t1,(void **)&pret);//等待t1线程退出
printf("t1 quit ret=%d\n",*pret);//打印t1线程退出时传出的数据
运行结果:
线程的取消
线程取消不是想取消就取消,必须有取消点才可以,线程的取消点主要是阻塞的系统调用
比如主线程需要取消子线程,执行完pthread_cancel(pid)后,子线程并不会被立马取消,而是会等待到阻塞的时候才会被取消,比如sleep的时候。
函数原型及头文件
#include <pthread.h>
int pthread_cancel(pthread_t thread);
参数:thread:线程pid号
返回值:成功返回0,不成功返回错误码
手动创建一个取消点
函数原型及头文件
#include <pthread.h>
void pthread_testcancel(void);
测试代码:
void *thread_fun(void* arg)
{while(1){pthread_testcancel();//手动设置一个取消点}
}int main()
{pthread_t tid;int arg = 10;int ret = pthread_create(&tid, NULL, thread_fun, NULL);if(ret == 0){printf("create succes\n");}sleep(3);pthread_cancel(tid);//取消线程while(1){}return 0;
}
运行:
如果没有手动取消点:
设置取消状态
设置线程的状态,可设置为不可取消或可取消。取消点可取消需要建立在线程的取消状态为可取消
函数原型及头文件
#include <pthread.h>
int pthread_setcancelstate(int state, int* oldstate);
参数:
- state:取消状态,PTHREAD_CANCEL_ENABLE,PTHREAD_CANCEL_DISABLE
- oldstate:旧的状态
返回值:成功返回0,不成功返回错误码。
代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_fun(void* arg)
{pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);//设置线程取消状态为不可取消while(1){pthread_testcancel();}
}int main()
{pthread_t tid;int arg = 10;int ret = pthread_create(&tid, NULL, thread_fun, NULL);if(ret == 0){printf("create succes\n");}sleep(3);pthread_cancel(tid);//取消子线程while(1){}return 0;
}
运行: 5s后更改状态为可取消:
设置取消类型
设置线程的取消类型,默认为有取消点才可取消,同时可设置为可以立马取消。
函数原型及头文件
#include <pthread.h>
int pthread_setcanceltype(int type, int* oldtype);
参数:
- type:要设置的取消类型, PTHREAD_CANCEL_DEFERRED, (需要有取消点) PTHREAD_CANCEL_ASYNCHRONOUS
- oldtype:旧的取消类型
返回值:成功返回0,不成功返回错误码。
代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void *thread_fun(void* arg)
{pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);//设置为不需要取消点即可取消线程while(1){//pthread_testcancel();}
}int main()
{pthread_t tid;int arg = 10;int ret = pthread_create(&tid, NULL, thread_fun, NULL);if(ret == 0){printf("create succes\n");}sleep(3);pthread_cancel(tid);while(1){}return 0;
}
运行:
线程的清理
子线程运行时,申请了一块内存还没内有释放的时候,被主线程取消了,这就会造成内存泄漏,这是不好的,所以我们需要进行线程的清理,这是很有必要的!!!
函数原型及头文件
#include <pthread.h>
void pthread_cleanup_push(void(*routine)(void*), void* arg);
void pthread_cleanup_pop(int execute);
注意:这俩个函数必须成对使用,不然编译会出错!
参数:
- routine:执行函数
- arg:执行函数的参数
- execute:0-不执行pthread_cleanup_push 非0-执行pthread_cleanup_push
函数使用tip:pthread_cleanup_push函数被触发后会跳转到routine函数中执行,pthread_cleanup_push会被触发的条件:
- 被pthread_cancel取消掉(必须建立不可0执行pthread_cleanup_pop函数)
- 执行pthread_exit(必须建立不可0执行pthread_cleanup_pop函数)
- 非0执行pthread_cleanup_pop函数,无需被取消或exit退出线程
- return不可触发
上面的条件需要自己缕清一下思路,如果不清楚就可以看看下面的实例代码:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>void clean_func(void* arg)
{printf("执行清理工作\n");
}void *thread_fun(void* arg)
{pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);pthread_cleanup_push(clean_func, NULL);pthread_cleanup_pop(0);//参数0执行了pthread_cleanup_pop,所以后面的pthread_exit根本触发不了pthread_cleanup_pushpthread_exit(0);while(1){}
}int main()
{pthread_t tid;int arg = 10;int ret = pthread_create(&tid, NULL, thread_fun, NULL);if(ret == 0){printf("create succes\n");}sleep(3);while(1){}return 0;
}
运行:
稍微修改一下子线程函数:
void *thread_fun(void* arg)
{pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);pthread_cleanup_push(clean_func, NULL);pthread_exit(0);//线程根本运行不到这里,因为前面已经exit了,这里完全是为了满足成对使用编译不出错pthread_cleanup_pop(0);while(1){}
}
运行:
再修改一下子线程代码,实现条件3:
void *thread_fun(void* arg)
{pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);pthread_cleanup_push(clean_func, NULL);//非0执行pthread_cleanup_pop函数,无需被取消或exit退出线程即可触发pthread_cleanup_pop(1);while(1){}
}
运行:
二、互斥锁的使用
互斥锁的初始化
函数原型及头文件
#include <pthread.h>
int pthread_mutex_init(phtread_mutex_t *mutex, const pthread_mutexattr_t *restrict attr);
参数:
- mutex:互斥量指针
- restrict attr:互斥量属性,一般为NULL缺省属性
返回值:成功返回0,不成功返回错误码
互斥量加锁/解锁
函数原型及头文件
#include <pthread.h>
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);
参数:mutex:互斥量指针
返回值:成功返回0
lock 函数与 unlock 函数分别为加锁解锁函数,只需要传入已经初始化好的 pthread_mutex_t 互斥量指针。成功后会返回 0 。当某一个线程获得了执行权后,执行 lock 函数,一旦加锁成功后,其余线程遇到 lock 函数时候会发生阻塞,直至获取资源的线程执行 unlock 函数后。unlock 函数会唤醒其他正在等待互斥量的线程
销毁互斥量
函数原型及头文件
#include <pthread.h>
int pthread_mutex_destory(pthread_mutex_t *mutex);
参数:mutex:互斥量指针
返回值:成功返回0
三、条件变量使用
创建和销毁条件变量
函数原型及头文件
#include <pthread.h>
// 初始化条件变量
int pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *cond_attr);
//cond_attr 通常为 NULL// 销毁条件变量
int pthread_cond_destroy(pthread_cond_t *cond);
//这些函数成功时都返回 0
参数:
- cond:条件变量指针
- cond_attr:条件变量属性,一般为NULL缺省属性
返回值:成功返回0,不成功返回错误码
等待条件变量
函数原型及头文件
#include <pthread.h>int pthread_cond_wait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex);
int pthread_cond_timedwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, cond struct timespec *restrict timeout);
参数:
- cond:条件变量指针
- mutex:互斥量指针
返回值:成功返回0,不成功返回错误码
pthread_cond_wait函数行为如下:
- 解锁互斥锁:调用 pthread_cond_wait 的线程首先会释放(解锁)它当前持有的互斥锁。这一步是必要的,因为条件变量通常与互斥锁一起使用,以确保对共享数据的访问是同步的。解锁互斥锁允许其他线程获取该锁,从而可以安全地修改共享数据。
- 加入等待队列:在解锁互斥锁之后,调用 pthread_cond_wait 的线程会将自己添加到与该条件变量相关联的等待队列中。此时,线程进入阻塞状态,等待被唤醒。
阻塞并等待信号:线程在等待队列中保持阻塞状态,直到它收到一个针对该条件变量的信号(通过 pthread_cond_signal 或 pthread_cond_broadcast 发出)。需要注意的是,仅仅因为线程在等待队列中并不意味着它会立即收到信号;它必须等待直到有其他线程显式地发出信号
- 重新获取互斥锁:当线程收到信号并准备从 pthread_cond_wait 返回时,它首先会尝试重新获取之前释放的互斥锁。如果此时锁被其他线程持有,那么该线程会阻塞在互斥锁的等待队列中,直到获得锁为止。这一步确保了线程在继续执行之前能够重新获得对共享数据的独占访问权。
检查条件:一旦线程成功获取到互斥锁,它会再次检查导致它调用 pthread_cond_wait 的条件是否现在满足。虽然通常认为在收到信号时条件已经满足,但这是一个编程错误的常见来源。正确的做法是在每次从 pthread_cond_wait 返回后都重新检查条件,因为可能有多个线程在等待相同的条件,或者条件可能在信号发出和线程被唤醒之间发生变化
- 返回并继续执行:如果条件满足,线程会从 pthread_cond_wait 返回,并继续执行后续的代码。如果条件仍然不满足,线程可以选择再次调用 pthread_cond_wait 进入等待状态,或者执行其他操作。
简单点描述就是需要调用通知函数的线程调用通知函数并且释放互斥量。等待函数才能顺利成功返回
使用需要配合互斥量使用:
pthread_mutex_lock(&g_tMutex);
// 如果条件不满足则,会 unlock g_tMutex
// 条件满足后被唤醒,会 lock g_tMutex
pthread_cond_wait(&g_tConVar, &g_tMutex);
/* 操作临界资源 */
pthread_mutex_unlock(&g_tMutex);
这里的条件不满足表示wait函数没有被唤醒,这涉及到下一个函数,先看上面的代码:线程先lock(持有互斥锁),这时其他线程如果也想获得这个锁就会被阻塞,该线程代码继续执行到pthread_cond_wait 函数时,该线程会释放锁,并进入阻塞状态等待被其他线程唤醒;等其他线程调用唤醒函数后,该线程才会执行wait函数之后的代码,此时该线程持有互斥锁,最后该线程主动释放互斥锁。
通知条件变量
函数原型及头文件
这两个函数可以用于通知线程条件已经满足。pthread_cond_signal函数将唤醒等待该条件的某个线程,而pthread_cond_broadcast函数将唤醒等待该条件的所有进程。
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond);
参数:
- cond:条件变量指针
返回值:成功返回0,不成功返回错误码
相关文章:
Linux线程
一、线程的使用 线程创建 函数原型及头文件 #include <pthread.h> int pthread_create(pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void *(*start_rtn)(void *), void *restrict arg); 参数: tidp:当pthread_create成功…...
Keepalive+LVS+Nginx+NFS高可用项目
项目架构 分析 主机规划 主机系统安装应用网络IPclientredhat 9.5无NAT172.25.250.115/24lvs-masterrocky 9.5ipvsadm,keepalivedNAT172.25.250.116/24 VIP 172.25.250.100/32lvs-backuprocky 9.5ipvsadm,keepalivedNAT172.25.250.117/24 VIP 172.25.2…...
在线编辑数学公式
参考工具: https://www.processon.com/mathtype https://www.latexlive.com/ 一、简单好用的数学公式编辑工具推荐 1. MathType / AxMath • 特点:专业公式编辑软件,支持与Word、WPS等办公软件无缝集成,提供丰富的数学符号和模…...
【spring Cloud Netflix】OpenFeign组件
1.概述 Feign旨在使编写Java Http客户端变得更容易。前面在使用RibbonRestTemplate进行服务的远程调用 时,利用RestTemplate对Http请求的封装处理,形成了一套模板化的调用方法。但是在实际开发中,由 于对服务的依赖调用可不止一处࿰…...
基于Flask的Windows命令大全Web应用技术解析与架构设计
基于Flask的Windows命令大全Web应用技术解析与架构设计 引言 Windows命令行工具是系统管理和开发调试的核心技能之一。然而,许多用户对常用命令的用法和场景并不熟悉。本文通过一个基于Flask框架开发的Web应用,系统性地整理了50个Windows命令的用法&…...
Qt中左侧项目菜单中构建设置功能中的构建步骤是怎么回事
在 Qt Creator 中,**构建设置(Build Settings)下的构建步骤(Build Steps)**是控制项目如何编译、链接和生成最终产物的核心配置区域。它允许你自定义编译过程中的各个阶段(如 qmake、make、cmake 等命令的具…...
(一)从零开始:用 LangChain 和 ZhipuAI 搭建简单对话
最近一直在研究如何用 LangChain 和 ZhipuAI 搭建一个智能对话系统,发现这个组合真的非常强大,而且实现起来并不复杂。今天就来分享一下我的学习过程和一些心得体会,希望能帮到同样在探索这个领域的小伙伴们。 一、 环境搭建:从零…...
Java大厂面试题 -- JVM 优化进阶之路:从原理到实战的深度剖析(2)
最近佳作推荐: Java大厂面试题 – 深度揭秘 JVM 优化:六道面试题与行业巨头实战解析(1)(New) 开源架构与人工智能的融合:开启技术新纪元(New) 开源架构的自动化测试策略优…...
C++ 标准库参考手册深度解析
C 标准库参考手册是每个 C 开发者的必备工具。本文将系统性解析其架构设计、核心功能及实战应用技巧,帮助开发者构建高效的知识检索与代码开发工作流,涵盖从语法查询到编译器适配的全流程技术细节。 一、网站架构与技术细节 1. 信息组织体系 1.1 层级化…...
单片机学习笔记8.定时器
IAP15W4K58S4定时/计数器结构工作原理 定时器工作方式控制寄存器TMOD 不能进行位寻址,只能对整个寄存器进行赋值 寄存器地址D7D6D5D4D3D2D1D0复位值TMOD89HGATEC/(T低电平有效)M1M0GATEC/(T低电平有效)M1M000000000B D0-D3为T0控制,D4-D7为T1控制 GAT…...
神经网络入门:生动解读机器学习的“神经元”
神经网络作为机器学习中的核心算法之一,其灵感来源于生物神经系统。在本文中,我们将带领大家手把手学习神经网络的基本原理、结构和训练过程,并通过详细的 Python 代码实例让理论与实践紧密结合。无论你是编程新手还是机器学习爱好者…...
2025-04-05 吴恩达机器学习5——逻辑回归(2):过拟合与正则化
文章目录 1 过拟合1.1 过拟合问题1.2 解决过拟合 2 正则化2.1 正则化代价函数2.2 线性回归的正则化2.3 逻辑回归的正则化 1 过拟合 1.1 过拟合问题 欠拟合(Underfitting) 模型过于简单,无法捕捉数据中的模式,导致训练误差和测试误…...
美团滑块 分析
声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 逆向过程 距离识别不准简单学习一下&…...
C++ atomic 原子操作
一、原子操作简介 在多线程编程中,通常我们需要多个线程共享数据。但如果不加以控制,多个线程同时访问同一数据,可能会导致数据不一致或竞争条件(race conditions)。为了解决这个问题,我们引入了 原子操作…...
Leetcode - 双周赛153
目录 一、3498. 字符串的反转度二、3499. 操作后最大活跃区段数 I三、3500. 将数组分割为子数组的最小代价四、3501. 操作后最大活跃区段数 II 一、3498. 字符串的反转度 题目连接 本题直接模拟,代码如下: class Solution {public int reverseDegree(…...
25.4 GLM-4+RAG智能标注实战:标注成本暴降60%,检索准确率飙升40%!
使用 GLM-4 优化 RAG 程序:智能标注提升检索质量 关键词:GLM-4 数据标注, RAG 优化, 检索增强生成, 向量数据库, 语义关联度分析 1. RAG 数据标注的核心挑战 在检索增强生成(Retrieval-Augmented Generation)系统中,检索数据的标注质量直接影响最终生成效果。传统标注方…...
基于sklearn实现文本摘要思考
和各位小伙伴分享一下使用sklearn进行文本摘要的思考。 第一版本 原理 提取式文本摘要的基本原理是: 将文本分割成句子 计算每个句子的重要性(权重) 选择权重最高的几个句子组成摘要 常用的句子权重计算方法: TF-IDF:基于词频-逆文档频…...
Cortex-M3 NVIC可以控制异常向量表的哪些部分
Cortex-M3 的 NVIC(嵌套向量中断控制器)不直接控制整个异常向量表,但可以管理向量表中与中断相关的部分行为。以下是 NVIC 对异常向量表的具体控制范围和相关机制: 1. NVIC 直接控制的部分 NVIC 主要管理 外部中断(IRQ) 和部分 系统异常 的行为,但对向量表本身的存储位…...
AI朝代应避免AI幻觉:分析与应对策略
随着人工智能(AI)技术的不断发展,AI的应用领域已经涵盖了文本生成、图像与视频创作以及程序编写等多个方面。然而,AI的生成能力并非没有缺陷,其中最为显著的之一就是所谓的“AI幻觉”(AI hallucination&…...
网络传输H.264方法对比
一、引言 网络传输H.264有多种方法,包括但不限于:1.通过RTP直接传输H.264;2.通过UDP传输TS流;3.通过RTP传输TS流;4.通过RTP传输PS流。本文对这些方法进行对比。 二、通过RTP直接传输H.264 这种方案就是RTP包…...
第九章:可靠通信_《凤凰架构:构建可靠的大型分布式系统》
第九章 可靠通信 一、零信任网络模型 核心难点:理解安全模型从传统边界防护到动态信任验证的转变 零信任的核心原则 不再区分"内部可信网络"与"外部不可信网络"(传统防火墙模型失效)每次请求都需要进行身份验证和授权…...
HeidiSQL:多数据库管理工具
HeidiSQL 是一款广受欢迎的免费开源数据库管理工具,专为数据库管理员及开发者设计。无论您是刚接触数据库领域的新手,还是需要同时处理多种数据库系统的专业开发者,该工具都能凭借其直观的界面和强大的功能,助您轻松完成数据管理任…...
文件系统-inode/软硬件连接(未完结)
首先我们了解一下文件简洁理解来说就是:文件内容文件属性 ---> 磁盘上存储的文件存文件的内容存文件的属性;而文件的内容----存放在每个数据块 ;文件属性存放在iNode里面。 要明白:linux系统中的文件是存储在磁盘中的…...
数据库并发控制问题
并发控制问题是数据库管理系统(DBMS)中处理多个事务并发执行时,确保数据一致性、可靠性和完整性的一系列技术和挑战。并发控制问题通常与事务的隔离性和事务之间的相互影响有关。以下是并发控制中主要的几种问题及其解决方式的详细解释&#…...
(五)智能体与工具协同——打造智能对话的超级助手
上一篇:(四)数据检索与增强生成——让对话系统更智能、更高效 在前四个阶段,我们已经搭建了一个功能强大的智能对话,并深入探讨了输入输出处理、链式工作流构建和数据检索与增强生成的细节。现在,我们将进…...
第十三届蓝桥杯 2022 省 B 刷题统计
题目描述 小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做 a a a 道题目,周六和周日每天做 b b b 道题目。请你帮小明计算,按照计划他将在第几天实现做题数大于等于 n n n 题? 输入格式 输入一行包含三个整数 a , b a, b a,b 和 n n n. 输出格…...
NLP/大模型八股专栏结构解析
1.transformer 结构相关 (1)transformer的基本结构有哪些,分别的作用是什么,代码实现。 NLP高频面试题(一)——Transformer的基本结构、作用和代码实现 (2)LSTM、GRU和Transformer结…...
不在 qtdesigner中提升,进行主题程序设计
以下是无需在Qt Designer中提升控件的完整主题化方案,保持现有代码结构的同时实现动态阴影效果管理: 一、增强主题管理器(支持动态控件发现) // thememanager.h #pragma once #include <QObject> #include <QSet> #…...
TDengine 3.3.6.0 版本中非常实用的 Cols 函数
简介 在刚刚发布的 TDengine 3.3.6.0 版本 中,新增了一个非常实用的 函数COLS ,此函数用于获取选择函数所在行列信息,主要应用在生成报表数据,每行需要出现多个选择函数结果,如统计每天最大及最小电压,并报…...
MessageQueue --- RabbitMQ WorkQueue and Prefetch
MessageQueue --- RabbitMQ WorkQueue and Prefetch 什么是WorkQueue分发机制 --- RoundRobin分发机制 --- PrefetchSpring example use prefetch --- Fair Dispatch 什么是WorkQueue Work queues,任务模型。简单来说就是让多个消费者绑定到一个队列,共同…...
第四章:透明多级分流系统_《凤凰架构:构建可靠的大型分布式系统》
第四章:透明多级分流系统 一、客户端缓存 核心目标:减少重复请求,降低服务端压力。 1. 强制缓存 定义:客户端直接根据缓存规则决定是否使用本地缓存,无需与服务端交互。关键HTTP头: Cache-Control&#…...
题解:AT_abc241_f [ABC241F] Skate
一道经典的 bfs 题。 提醒:本题解是为小白专做的,不想看的大佬请离开。 这道题首先一看就知道是 bfs,但是数据点不让我们过: 1 ≤ H , W ≤ 1 0 9 1\le H,W\le10^9 1≤H,W≤109。 那么我们就需要优化了,从哪儿下手…...
热题100-字母异位词分组
方法用Arrays.sort对每个String 进行排序,毕竟排序以后都一样了,然后放入Map中的key跟value,可以一对多,然后返回的时候只要返回Map中所有的values就可以了 class Solution {public List<List<String>> groupAnagram…...
WiFi加密协议
目录 1. 认证(Authentication) 1.1 开放系统认证(Open System Authentication) 1.2 共享密钥认证(Shared Key Authentication) 1.3 802.1X/EAP认证(企业级认证) 2. 关联(Association) 3. 加密协议(Security Handshake) 整体流程总结…...
【AI提示词】书籍推荐专家
提示说明 帮助您找到适合您的好书。 提示词 ## Role: 书籍推荐专家## Profile: - author: xxx - version: 1.0.0 - language: 中文 - description: 我是一位书籍推荐专家,我可以帮助您找到适合您的好书。## Goals: - 吸引读者的注意力,引导他们阅读更…...
Linux进程间通信——有名管道
一.概念 函数形式:int mkfifo(const char \*filename,mode_t mode); 功能:创建管道文件 参数:管道文件文件名\路径,权限,创建的文件权限仍然和umask有关系。 返回值:创建成功返回0,创建失败返回…...
JavaScript基础--01-JS简介
字面量:数字、字符串、布尔值 前言JavaScript背景Web前端有三层:发展历史JavaScript的发展:蒸蒸日上 JavaScript介绍JavaScript入门易学性JavaScript是脚本语言JavaScript的组成 JavaScript 的特点特点1:解释型语言特点2ÿ…...
2025年 能够有效提升AI的生成质量和逻辑严谨性 的通用型系统提示
以下是三个经过精心设计的通用型系统提示(System Prompt),能够有效提升AI的生成质量和逻辑严谨性,适用于各类对话、分析和创作场景: Prompt 1 - 专家级分步验证模式 你是一个具备跨领域知识整合能力的超级AIÿ…...
xss攻击
XSS 攻击,即跨站脚本攻击(Cross - Site Scripting),是一种常见的 Web 应用程序安全漏洞。以下是关于它的详细介绍: 原理 输入输出控制不严:程序对用户输入和输出处理不当。用户输入的数据没有经过充分的过…...
Node.js核心模块及Api详解
以下是 Node.js 最常用的核心模块及 API 详解,按使用频率和重要性分类整理: 一、高频核心模块 1. fs 文件系统 const fs require(fs); const fsPromises require(fs).promises; // Promise 版本// 异步读取文件(推荐) fs.read…...
解析keras.layers.Layer中的权重参数
文章目录 概要__init__()build()add_weight() 概要 keras.layers.Layers是所有层对象的父类,在keras.layers下所有实现类都是其子类,自定义层时需要继承该类。 init() Layer的构造函数,需要注意两个参数trainable和name trainable:指定该层…...
原型设计工具即时设计的简单使用攻略
即时设计是一款国产在线协同设计工具,支持从原型设计到开发交付的全流程,尤其擅长Web/App界面原型制作。其核心优势体现在: • 零门槛入门:浏览器直接访问无需安装,中文界面友好 • 资源生态完善:内置3000原…...
深入解析C++智能指针:从内存管理到现代编程实践
一、智能指针核心概念 1.1 智能指针的本质 智能指针是基于**RAII(资源获取即初始化)**的封装类,通过对象生命周期自动管理动态内存。与传统指针相比: 特性原始指针智能指针内存管理手动自动空指针检查需显式判断支持空状态检测…...
在 Langflow 中构建灵活的自定义组件:从基础到高级实践
本文深入探讨了如何在 Langflow 平台中创建功能丰富的自定义组件。通过详细的目录结构解析、分步实现指南和多个实战案例,帮助开发者掌握利用 Python 生态扩展低代码平台的方法,打造高效的数据处理流程。 理解组件架构设计 自定义组件是在 Langflow 中创…...
【数学建模】(时间序列模型)ARIMA时间序列模型
ARIMA时间序列模型详解及常见时间序列模型概览 文章目录 ARIMA时间序列模型详解及常见时间序列模型概览1 引言2 ARIMA模型的基本概念3 ARIMA模型的组成部分详解3.1 AR模型 (自回归模型)3.2 MA模型 (移动平均模型)3 I (差分) 4 ARIMA模型的建模步骤5 Python实现ARIMA模型6 常见时…...
模版的特性及其编译分离
1.模版的分类 模版参数分为 类型形参 和 非类型形参 类型形参:出现在模版参数列表中,跟在class和typename之后的参数类型名称 非类型形参:就是用一个常量作为类(函数)模版的一个参数,在类(函…...
8电池_多绕组反激式变压器均衡_4模式
(1)8节串联锂离子电池组 (2)多绕组双向反激式变压器,1个变压器解决多电池均衡 (3)亮点:支持1建切换4种均衡算法–>全网唯一 (4)多绕组变压器均衡也能设计多种均衡算法–>全网唯一 锂离子电池均衡,均衡拓扑,均衡算法...
6.1 python加载win32或者C#的dll的方法
python很方便的可以加载win32的方法以及C#编写的dll中的方法或者变量,大致过程如下。 一.python加载win32的方法,使用win32api 1.安装库win32api pip install win32api 2.加载所需的win32函数并且调用 import win32api win32api.MessageBox(0,"…...
STP学习
{所有内容均来自于西安欧鹏的陈俊老师} STP生成树 当二层交换机意外成环路的时候会发生: 1.广播风暴:当广播帧进入环路时,会被不断复制并传输,导致网络中的广播流量急剧增加,消耗大量的网络带宽,降低网络…...
特征值与特征向量:从理论到应用的全面解析
特征值与特征向量:从理论到应用的全面解析 一、特征值与特征向量核心概念 定义 对于方阵 ( A ),若存在标量 ( \lambda ) 和非零向量 ( v ),使得: [ A v \lambda v ] 则 ( \lambda ) 为特征值,( v ) 为对应的特征向…...