C++:pthread的使用
pthread 简介
pthread 是 POSIX 线程(POSIX Threads)的简称,它是 POSIX 标准中定义的线程接口规范。pthread 库提供了一系列函数,用于创建、销毁、同步和管理线程。在类 Unix 系统(如 Linux、macOS)中,pthread 库被广泛使用,是实现多线程编程的重要工具。
基本使用方法
线程创建
使用 pthread_create 函数来创建一个新线程。其函数原型如下:
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
thread:指向 pthread_t 类型变量的指针,用于存储新创建线程的标识符。
attr:线程属性,通常设为 NULL,使用默认属性。
start_routine:指向线程函数的指针,线程启动后将执行该函数。
arg:传递给线程函数的参数。
#include <stdio.h>
#include <pthread.h>// 线程函数
void* thread_function(void* arg) {printf("This is a thread, argument: %d\n", *(int*)arg);return NULL;
}int main() {pthread_t thread;int arg = 10;// 创建线程if (pthread_create(&thread, NULL, thread_function, &arg)!= 0) {perror("Failed to create thread");return 1;}printf("Thread created successfully\n");// 等待线程结束if (pthread_join(thread, NULL)!= 0) {perror("Failed to join thread");return 1;}printf("Thread joined successfully\n");return 0;
}
线程等待
使用 pthread_join 函数等待一个线程结束。函数原型:
int pthread_join(pthread_t thread, void **retval);
thread:要等待的线程标识符。
retval:用于接收线程函数的返回值,通常设为 NULL。
线程销毁
可以使用 pthread_cancel 函数来取消一个线程。函数原型:
int pthread_cancel(pthread_t thread);
thread:要取消的线程标识符。
注意,被取消的线程需要有相应的清理机制,否则可能会导致资源泄漏。
传参实例
#include <iostream>
#include <pthread.h>
#include <unistd.h>
using namespace std;
int j = 2;
void* pthread_fun(void *arg)
{while(j--){cout << " in pthread_task" << endl;cout << *(int*)arg << endl;sleep(1);}// 线程返回一个整数值int* result = new int(42);return static_cast<void*>(result);//pthread_exit(reinterpret_cast<void*>(result));}int main()
{int ret = 0;pthread_t tid = 0;int argsend = 99;int i = 3;ret = pthread_create(&tid, NULL, pthread_fun, &argsend);if(ret != 0){cout << " pthread_create error" << endl;return -1;}while(i--){cout << "pthread _create success" << endl;sleep(2);//等待回收资源}void* ret1;// 阻塞式等待线程结束,并获取返回值if (pthread_join(tid, &ret1) != 0) {std::cerr << "Failed to join thread." << std::endl;return 1;}// 处理线程的返回值int* result = static_cast<int*>(ret1);std::cout << "Thread returned: " << *result << std::endl;// 释放动态分配的内存delete result;return 0;
}
线程同步
多线程编程中,线程同步是至关重要的。pthread 提供了多种同步机制,如互斥锁、条件变量、信号量等。
互斥锁
互斥锁用于保证同一时刻只有一个线程能够访问共享资源。使用 pthread_mutex_t 类型来定义互斥锁,相关函数有:
pthread_mutex_init:初始化互斥锁。
pthread_mutex_lock:加锁,若锁已被占用则线程阻塞。
pthread_mutex_unlock:解锁。
pthread_mutex_destroy:销毁互斥锁。
#include <stdio.h>
#include <pthread.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
int shared_variable = 0;void* increment(void* arg) {for (int i = 0; i < 1000; ++i) {pthread_mutex_lock(&mutex);shared_variable++;pthread_mutex_unlock(&mutex);}return NULL;
}int main() {pthread_t thread1, thread2;// 创建两个线程if (pthread_create(&thread1, NULL, increment, NULL)!= 0 ||pthread_create(&thread2, NULL, increment, NULL)!= 0) {perror("Failed to create thread");return 1;}// 等待线程结束if (pthread_join(thread1, NULL)!= 0 ||pthread_join(thread2, NULL)!= 0) {perror("Failed to join thread");return 1;}printf("Shared variable value: %d\n", shared_variable);// 销毁互斥锁pthread_mutex_destroy(&mutex);return 0;
}
thread_function1线程在条件ready为false时等待,thread_function2线程在工作一段时间后将ready设置为true,并通过pthread_cond_signal唤醒thread_function1线程。
读写锁
#include <iostream>
#include <pthread.h>
#include <unistd.h>// 定义读写锁
pthread_rwlock_t rwlock;
// 共享数据
int sharedData = 0;// 读线程函数
void* reader(void* arg) {int id = *(int*)arg;while (true) {// 加读锁pthread_rwlock_rdlock(&rwlock);std::cout << "Reader " << id << " reads sharedData: " << sharedData << std::endl;// 释放读锁pthread_rwlock_unlock(&rwlock);// 模拟一些工作sleep(1);}return nullptr;
}// 写线程函数
void* writer(void* arg) {int id = *(int*)arg;while (true) {// 加写锁pthread_rwlock_wrlock(&rwlock);sharedData++;std::cout << "Writer " << id << " writes sharedData: " << sharedData << std::endl;// 释放写锁pthread_rwlock_unlock(&rwlock);// 模拟一些工作sleep(2);}return nullptr;
}int main() {// 初始化读写锁pthread_rwlock_init(&rwlock, nullptr);// 创建读线程和写线程pthread_t readers[3];pthread_t writers[2];int readerIds[3] = {1, 2, 3};int writerIds[2] = {1, 2};for (int i = 0; i < 3; ++i) {pthread_create(&readers[i], nullptr, reader, &readerIds[i]);}for (int i = 0; i < 2; ++i) {pthread_create(&writers[i], nullptr, writer, &writerIds[i]);}// 等待线程结束(这里实际上不会结束,因为线程是无限循环)for (int i = 0; i < 3; ++i) {pthread_join(readers[i], nullptr);}for (int i = 0; i < 2; ++i) {pthread_join(writers[i], nullptr);}// 销毁读写锁pthread_rwlock_destroy(&rwlock);return 0;
}
读写锁的定义和初始化:
pthread_rwlock_t rwlock;:定义一个读写锁变量 rwlock。
pthread_rwlock_init(&rwlock, nullptr);:在 main 函数中初始化读写锁,第二个参数为 nullptr 表示使用默认的属性。
共享数据:
int sharedData = 0;:定义一个共享的整数变量 sharedData,多个线程将对其进行读写操作。
读线程函数 reader:
pthread_rwlock_rdlock(&rwlock);:调用 pthread_rwlock_rdlock 函数加读锁,允许多个读线程同时持有读锁。
读取共享数据 sharedData 并输出。
pthread_rwlock_unlock(&rwlock);:调用 pthread_rwlock_unlock 函数释放读锁。
写线程函数 writer:
pthread_rwlock_wrlock(&rwlock);:调用 pthread_rwlock_wrlock 函数加写锁,写锁是独占的,同一时间只能有一个线程持有写锁。
对共享数据 sharedData 进行加 1 操作并输出。
pthread_rwlock_unlock(&rwlock);:调用 pthread_rwlock_unlock 函数释放写锁。
线程的创建和等待:
使用 pthread_create 函数创建 3 个读线程和 2 个写线程。
使用 pthread_join 函数等待线程结束,但由于线程是无限循环,实际上不会结束。
读写锁的销毁:
pthread_rwlock_destroy(&rwlock);:在程序结束时销毁读写锁,释放相关资源。
非阻塞式互斥锁
在多线程编程中,常规的互斥锁在获取锁时,如果锁已被占用,线程会进入阻塞状态,一直等待锁的释放。而非阻塞式互斥锁则不同,当线程尝试获取锁时,如果锁当前不可用,它不会阻塞线程,而是立即返回一个表示获取锁失败的状态,线程可以根据这个状态决定后续操作。这种特性在一些对响应时间要求极高,且线程不能长时间等待的场景中非常有用。
在 C++ 中,使用 pthread 库实现非阻塞式互斥锁时,可以利用pthread_mutex_trylock函数
#include <iostream>
#include <pthread.h>
#include <unistd.h>// 定义互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 线程函数
void* threadFunction(void* arg) {// 尝试获取非阻塞式互斥锁if (pthread_mutex_trylock(&mutex) == 0) {std::cout << "Thread got the non - blocking mutex." << std::endl;sleep(1); // 模拟一些工作pthread_mutex_unlock(&mutex);std::cout << "Thread released the non - blocking mutex." << std::endl;} else {std::cout << "Thread couldn't get the non - blocking mutex." << std::endl;}return nullptr;
}int main() {pthread_t thread;// 初始化互斥锁if (pthread_mutex_init(&mutex, nullptr)!= 0) {std::cerr << "Failed to initialize mutex" << std::endl;return 1;}// 主线程先获取锁if (pthread_mutex_lock(&mutex)!= 0) {std::cerr << "Failed to lock mutex in main thread" << std::endl;return 1;}// 创建线程if (pthread_create(&thread, nullptr, threadFunction, nullptr)!= 0) {std::cerr << "Failed to create thread" << std::endl;pthread_mutex_unlock(&mutex);return 1;}sleep(2); // 主线程保持锁一段时间pthread_mutex_unlock(&mutex); // 主线程释放锁// 等待线程结束if (pthread_join(thread, nullptr)!= 0) {std::cerr << "Failed to join thread" << std::endl;return 1;}// 销毁互斥锁if (pthread_mutex_destroy(&mutex)!= 0) {std::cerr << "Failed to destroy mutex" << std::endl;return 1;}return 0;
}
threadFunction线程尝试使用pthread_mutex_trylock获取互斥锁,如果获取成功则执行相关操作并释放锁,否则输出获取失败的信息。主线程先获取锁并保持一段时间,模拟锁被占用的情况,展示非阻塞式互斥锁的工作机制。
非阻塞式读写锁锁
读写锁区分了读操作和写操作,允许多个线程同时进行读操作,但只允许一个线程进行写操作。非阻塞式读写锁在获取读锁或写锁时,如果锁被占用,不会阻塞线程,而是立即返回获取结果。
在 C++ 中,使用 pthread 库实现非阻塞式读写锁,读锁可以通过pthread_rwlock_tryrdlock函数尝试获取,写锁可以通过pthread_rwlock_trywrlock函数尝试获取。
#include <iostream>
#include <pthread.h>
#include <unistd.h>// 定义读写锁
pthread_rwlock_t rwLock = PTHREAD_RWLOCK_INITIALIZER;
int sharedData = 0;// 读线程函数
void* readThreadFunction(void* arg) {// 尝试获取非阻塞式读锁if (pthread_rwlock_tryrdlock(&rwLock) == 0) {std::cout << "Read thread got the non - blocking read lock. Data: " << sharedData << std::endl;sleep(1); // 模拟读操作pthread_rwlock_unlock(&rwLock);std::cout << "Read thread released the non - blocking read lock." << std::endl;} else {std::cout << "Read thread couldn't get the non - blocking read lock." << std::endl;}return nullptr;
}// 写线程函数
void* writeThreadFunction(void* arg) {// 尝试获取非阻塞式写锁if (pthread_rwlock_trywrlock(&rwLock) == 0) {sharedData++;std::cout << "Write thread got the non - blocking write lock. Data updated: " << sharedData << std::endl;sleep(1); // 模拟写操作pthread_rwlock_unlock(&rwLock);std::cout << "Write thread released the non - blocking write lock." << std::endl;} else {std::cout << "Write thread couldn't get the non - blocking write lock." << std::endl;}return nullptr;
}int main() {pthread_t readThread, writeThread;// 初始化读写锁if (pthread_rwlock_init(&rwLock, nullptr)!= 0) {std::cerr << "Failed to initialize rwlock" << std::endl;return 1;}// 创建读线程if (pthread_create(&readThread, nullptr, readThreadFunction, nullptr)!= 0) {std::cerr << "Failed to create read thread" << std::endl;pthread_rwlock_destroy(&rwLock);return 1;}// 创建写线程if (pthread_create(&writeThread, nullptr, writeThreadFunction, nullptr)!= 0) {std::cerr << "Failed to create write thread" << std::endl;pthread_cancel(readThread);pthread_rwlock_destroy(&rwLock);return 1;}// 等待读线程结束if (pthread_join(readThread, nullptr)!= 0) {std::cerr << "Failed to join read thread" << std::endl;return 1;}// 等待写线程结束if (pthread_join(writeThread, nullptr)!= 0) {std::cerr << "Failed to join write thread" << std::endl;return 1;}// 销毁读写锁if (pthread_rwlock_destroy(&rwLock)!= 0) {std::cerr << "Failed to destroy rwlock" << std::endl;return 1;}return 0;
}
readThreadFunction线程尝试使用pthread_rwlock_tryrdlock获取非阻塞式读锁,writeThreadFunction线程尝试使用pthread_rwlock_trywrlock获取非阻塞式写锁,根据获取结果进行相应操作,展示了非阻塞式读写锁在 pthread 中的使用方法。
条件变量
条件变量用于线程间的同步,一个线程可以在某个条件不满足时等待,另一个线程在条件满足时唤醒等待的线程。使用 pthread_cond_t 类型定义条件变量,相关函数有:
pthread_cond_init:初始化条件变量。
pthread_cond_wait:等待条件变量,调用时会自动释放互斥锁,当被唤醒时会重新获取互斥锁。
pthread_cond_signal:唤醒一个等待的线程。
pthread_cond_broadcast:唤醒所有等待的线程。
pthread_cond_destroy:销毁条件变量。
#include <iostream>
#include <pthread.h>
#include <unistd.h>// 互斥锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
// 条件变量
pthread_cond_t cond_var = PTHREAD_COND_INITIALIZER;
// 共享数据
bool ready = false;// 线程函数1
void* thread_function1(void* arg) {// 加锁pthread_mutex_lock(&mutex);while (!ready) {// 等待条件变量,此时会自动释放互斥锁pthread_cond_wait(&cond_var, &mutex);}std::cout << "Thread 1: Condition is met, continuing execution." << std::endl;// 解锁pthread_mutex_unlock(&mutex);return nullptr;
}// 线程函数2
void* thread_function2(void* arg) {sleep(2); // 模拟一些工作// 加锁pthread_mutex_lock(&mutex);ready = true;std::cout << "Thread 2: Setting condition to true and signaling." << std::endl;// 唤醒一个等待的线程pthread_cond_signal(&cond_var);// 解锁pthread_mutex_unlock(&mutex);return nullptr;
}int main() {pthread_t thread1, thread2;// 创建线程1if (pthread_create(&thread1, nullptr, thread_function1, nullptr)!= 0) {std::cerr << "Failed to create thread 1" << std::endl;return 1;}// 创建线程2if (pthread_create(&thread2, nullptr, thread_function2, nullptr)!= 0) {std::cerr << "Failed to create thread 2" << std::endl;pthread_cancel(thread1);return 1;}// 等待线程1结束if (pthread_join(thread1, nullptr)!= 0) {std::cerr << "Failed to join thread 1" << std::endl;}// 等待线程2结束if (pthread_join(thread2, nullptr)!= 0) {std::cerr << "Failed to join thread 2" << std::endl;}// 销毁互斥锁pthread_mutex_destroy(&mutex);// 销毁条件变量pthread_cond_destroy(&cond_var);return 0;
}
信号量
信号量用于控制对共享资源的访问数量。使用 sem_t 类型定义信号量,相关函数有:
sem_init:初始化信号量。
sem_wait:等待信号量,若信号量值为 0 则线程阻塞。
sem_post:释放信号量,使信号量值加 1。
sem_destroy:销毁信号量。
#include <iostream>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>// 定义信号量,初始值设为3,表示最多允许3个线程同时访问共享资源
sem_t semaphore;
// 共享资源
int sharedResource = 0;// 线程函数
void* threadFunction(void* arg) {// 等待信号量,获取访问共享资源的许可sem_wait(&semaphore);std::cout << "Thread " << *(int*)arg << " is accessing the shared resource." << std::endl;// 模拟对共享资源的操作sharedResource++;sleep(1);std::cout << "Thread " << *(int*)arg << " is leaving the shared resource." << std::endl;// 释放信号量,允许其他线程访问共享资源sem_post(&semaphore);return nullptr;
}int main() {// 初始化信号量,初始值为3if (sem_init(&semaphore, 0, 3)!= 0) {std::cerr << "Failed to initialize semaphore" << std::endl;return 1;}pthread_t threads[5];int threadIds[5] = {1, 2, 3, 4, 5};// 创建5个线程for (int i = 0; i < 5; ++i) {if (pthread_create(&threads[i], nullptr, threadFunction, &threadIds[i])!= 0) {std::cerr << "Failed to create thread " << i << std::endl;// 清理已创建的线程for (int j = 0; j < i; ++j) {pthread_cancel(threads[j]);}// 销毁信号量sem_destroy(&semaphore);return 1;}}// 等待所有线程结束for (int i = 0; i < 5; ++i) {if (pthread_join(threads[i], nullptr)!= 0) {std::cerr << "Failed to join thread " << i << std::endl;}}// 销毁信号量sem_destroy(&semaphore);std::cout << "Final value of shared resource: " << sharedResource << std::endl;return 0;
}
定义了一个信号量,初始值为 3,这意味着最多允许 3 个线程同时访问共享资源。每个线程在访问共享资源前,先通过sem_wait等待信号量,获取访问许可;访问结束后,通过sem_post释放信号量,允许其他线程访问。
相关文章:
C++:pthread的使用
pthread 简介 pthread 是 POSIX 线程(POSIX Threads)的简称,它是 POSIX 标准中定义的线程接口规范。pthread 库提供了一系列函数,用于创建、销毁、同步和管理线程。在类 Unix 系统(如 Linux、macOS)中&…...
Docker 容器安装 Dify的两种方法
若 Windows 已安装 Docker,可借助 Docker 容器来安装 Dify: 一、方法一 1. 拉取 Dify 镜像 打开 PowerShell 或命令提示符(CMD),运行以下命令从 Docker Hub 拉取 Dify 的镜像(Docker Hub中找到该命令行&…...
nodejs:express + js-mdict 作为后端,vue 3 + vite 作为前端,在线查询英汉词典
向 doubao.com/chat/ 提问: node.js js-mdict 作为后端,vue 3 vite 作为前端,编写在线查询英汉词典 后端部分(express js-mdict ) 1. 项目结构 首先,创建一个项目目录,结构如下࿱…...
mysql之事务深度解析与实战应用:保障数据一致性的基石
文章目录 MySQL 事务深度解析与实战应用:保障数据一致性的基石一、事务核心概念与原理1.1 事务的本质与意义1.2 事务的 ACID 特性1.2.1 原子性 (Atomicity)1.2.2 一致性 (Consistency)1.2.3 隔离性 (Isolation)1.2.4 持久性 (Durability) 1.3 事务隔离级别与并发问题…...
einops测试
文章目录 1. einops2. code3. pytorch 1. einops einops 主要是通过爱因斯坦标记法来处理张量矩阵的库,让矩阵处理上非常简单。 conda : conda install conda-forge::einopspython: 2. code import torch import torch.nn as nn import torch.nn.functional as…...
华为云deepseek大模型平台:deepseek满血版
华为云硅基流动使用Chatbox接入DeepSeek-R1满血版671B 1、注册: 华为云deepseek大模型平台注册:https://cloud.siliconflow.cn/i/aDmz6aVN 说明:填写邀请码的话邀请和被邀请的账号都会获得2000 万 Tokens;2个帐号间不会与其他关联…...
Elasticsearch Open Inference API 增加了对 Jina AI 嵌入和 Rerank 模型的支持
作者:Hemant Malik 及 Joan Fontanals Martnez 探索如何使用 Elasticsearch Open Inference API 访问 Jina AI 模型。 我们在 Jina AI 的朋友们将 Jina AI 的嵌入模型和重新排名产品的原生集成添加到 Elasticsearch 开放推理 API 中。这包括对行业领先的多语言文本嵌…...
在PHP Web开发中,实现异步处理有几种常见方式的优缺点,以及最佳实践推荐方法
1. 消息队列 使用消息队列(如RabbitMQ、Beanstalkd、Redis)将任务放入队列,由后台进程异步处理。 优点: 任务持久化,系统崩溃后任务不丢失。 支持分布式处理,扩展性强。 实现步骤: 安装消息…...
如何设计app测试用例
功能测试 测试方法:等价类划分法、边界值法、场景法、因果图法。优先级设定:核心业务功能设为高优先级。需求覆盖 正向场景、反向场景、关联接口串场景 与后端开发确认测试用例是否全面覆盖后端逻辑。和产品确认用例是否覆盖本次需求,以及是否…...
《炒股养家心法.pdf》 kimi总结
《炒股养家心法.pdf》这篇文章详细阐述了一位超级游资炒股养家的心得与技巧,展示了其从40万到10亿的股市传奇。以下是文章中炒股技巧和心得的详细总结: 1.核心理念 市场情绪的理解:炒股养家强调,股市的本质是群体博弈,…...
DVWA 靶场
DVWA 靶场的通关 刚建立和使用 输入 http://dvwa:8898/setup.php //进入用户名 密码 dvwa 你自己设计的想要进入数据库 点击creat 用户名 密码 admin passwordAttack type Sniper模式 在Sniper模式下,Payload字典用于逐个替换请求中标记的位置。例如&#x…...
【C语言】(一)数据在计算机中的存储与表示
目录 一、存储单位(比特/字节) 二、数制/进制(二/八/十/十六) 三、码制(原码/反码/补码/移码) 四、二进制表示小数 (一)定点数 (二)浮点数 十进制转化…...
大语言模型微调的公开JSON数据
大语言模型微调的公开JSON数据 以下是一些可用于大语言模型微调的公开JSON数据及地址: EmoLLM数据集 介绍:EmoLLM是一系列能够支持理解用户、帮助用户心理健康辅导链路的心理健康大模型,其开源了数据集、微调方法、训练方法及脚本等。数据集按用处分为general和role-play两种…...
solidity之Foundry安装配置(一)
一门面向合约的高级编程语言,主要用来编写以太坊只能合约。 Solidity受C语言,Python和js影响,但为编译成为以太坊虚拟机字节码在EVM上执行,很多特性和限制都和EVM相关。 Solidity 是静态类型语言,支持继承、库、自定义…...
【个人开源】——从零开始在高通手机上部署sd(二)
代码:https://github.com/chenjun2hao/qualcomm.ai 推理耗时统计 单位/ms 硬件qnncpu_clipqnncpu_unetqnncpu_vaehtp_cliphtp_unethtp_vae骁龙8 gen124716.994133440.39723.215411.097696.327 1. 下载依赖 下载opencv_x64.tar,提取码: rrbp下载opencv_aarch64.t…...
【精调】LLaMA-Factory 快速开始4 自定义个一个sharegpt数据集并训练
数据格式说明 LLaMA Factory:微调LLaMA3模型实现角色扮演 数据集 参考 开源模型应用落地-DeepSeek-R1-Distill-Qwen-7B-LoRA微调-LLaMA-Factory-单机单卡-V100(一) 大神给出的数据集的讲解:注册 如...
【Java】单例模式
单例模式 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法。 单例模式包含懒汉式和饿汉式,运行有且仅有一个实例化对象,只会…...
REACT--组件通信
组件之间如何进行通信? 组件通信 组件的通信主要借助props传递值 分为整体接收、解构接收 整体接收 import PropTypes from prop-types;//子组件 function Welcome(props){return (<div>hello Welcome,{props.count},{props.msg}</div>) }// 对 We…...
第16届蓝桥杯模拟赛3 python组个人题解
第16届蓝桥杯模拟赛3 python组 思路和答案不保证正确 1.填空 如果一个数 p 是个质数,同时又是整数 a 的约数,则 p 称为 a 的一个质因数。 请问, 2024 的最大的质因数是多少? 因为是填空题,所以直接枚举2023~2 &am…...
FFMPEG编码容错处理解决办法之途径----升级库文件
在qt开发环境下接收网络数据,调用ffmpeg解码播放视频,出现闪屏现象,具体现象可以使用操作系统自带的ffplay播放器播放原始视频流可复现;而使用操作系统自带的mpv播放器播放视频则不会出现闪屏;闪屏时会报Could not fin…...
kkFileView报错no office manager available
背景 部署环境:虚机Linux系统 发生问题的版本:4.1.0-SNAPSHOT 现象:有的docx文件可以预览,有的不可以。不可以的就怎么打开都不可以(不管你是躺着,站着,坐着,睡着,趴着都不行,哈哈) 报错内容 贴出主要的报错内容步骤: > no office manager available > tr…...
C++ 设计模式-模板方法模式
文件处理 #include <iostream>// 抽象基类:定义模板方法和抽象步骤 class DataProcessor { public:// 模板方法(固定流程)void Process() {OpenFile();ProcessData(); // 由子类实现CloseFile();}protected:virtual void ProcessData…...
MacOS下使用Ollama本地构建DeepSeek并使用本地Dify构建AI应用
目录 1 大白话说一下文章内容2 作者的电脑配置3 DeepSeek的本地部署3.1 Ollamal的下载和安装3.2 选择合适的deepseek模型3.3 安转deepseek 4 DifyDeepSeek构建Al应用4.1 Dify的安装4.1.1 前置条件4.1.2 拉取代码4.1.3 启动Dify 4.2 Dify控制页面4.3 使用Dify实现个“文章标题生…...
区块链相关方法-波士顿矩阵 (BCG Matrix)
波士顿矩阵(BCG Matrix),又称市场增长率 - 相对市场份额矩阵、波士顿咨询集团法、四象限分析法、产品系列结构管理法等,由美国著名的管理学家、波士顿咨询公司创始人布鲁斯・亨德森于 1970 年首创1。以下是关于波士顿矩阵的详细介…...
命令执行漏洞 Command Execute
命令执行漏洞(Command Injection)是一种安全漏洞,指的是攻击者能够在应用程序的命令行中注入并执行恶意命令。简单来说,就是攻击者可以利用这个漏洞让程序执行自己指定的命令,而不是程序原本应该执行的命令。 举个例子…...
黑马点评_商品信息缓存模块
保证缓存不要有空档期 删除后马上要写入中间不能插入任何阶段(如查询数据库) 对于单体系统1,将缓存与数据库操作放在同一个事务中(当前项目就是一个单体项目,所以选择这种方式) 对于分布式系统2,利用TCC(Tr…...
socket()函数的概念和使用案例
socket()函数的概念(C语言) 在C语言中,socket() 函数是用于创建一个新的套接字,它是网络编程的基础。套接字可以看作是不同计算机进程间通信的一个端点,允许数据在网络中的发送和接收。 socket() 函数的原型定义在 &l…...
【架构】事件驱动架构(Event - Driven Architecture,EDA)
一、事件驱动架构理论基础 事件驱动架构(Event - Driven Architecture,EDA)是一种软件设计范式,事件驱动的体系结构由生成事件流、侦听这些事件的事件使用者以及将事件从生成者传输到使用者的事件通道组成。 在事件驱动架构中,系统的行为由事件触发。事件可几乎实时发送,…...
三、linux字符驱动详解
在上一节完成NFS开发环境的搭建后,本节将探讨Linux字符设备驱动的开发。字符设备驱动作为Linux内核的重要组成部分,主要负责管理与字符设备(如串口、键盘等)的交互,并为用户空间程序提供统一的读写操作接口。 驱动代码…...
14.9 Auto-GPT 提示工程深度解析:设计具备自主决策能力的智能体大脑
Auto-GPT 提示工程深度解析:设计具备自主决策能力的智能体大脑 关键词:Auto-GPT 提示工程、结构化提示模板、工具调用触发、动态上下文管理、自主决策优化 1. 自主智能体提示设计的核心原则 Prompt 设计三维度模型: #mermaid-svg-jHMGjPZTQA8Op385 {font-family:"tre…...
【p-camera-h5】 一款开箱即用的H5相机插件,支持拍照、录像、动态水印与样式高度定制化。
【开源推荐】p-camera-h5:一款轻量级H5相机插件开发实践 一、插件背景 在Web开发中,原生摄像头功能的集成往往面临以下痛点: 浏览器兼容性问题视频流与水印叠加实现复杂移动端适配困难功能定制成本高 为此,p-camera-h5 —— 一…...
c++中sleep是什么意思(不是Sleep() )
sleep 函数在 C 语言中用于暂停程序执行指定的秒数,语法为 sleep(unsigned int seconds)。当 seconds 为 0 时,函数立即返回,否则函数将使进程暂停指定的秒数,并返回实际暂停的时间。 sleep 函数在 C 中的含义 sleep 函数是 C 标…...
优品指标树
目录 大势型 超买超卖型 超势型 能量型 成交量型 均线型 路径型 指南针经典指标 神系经典指标 庄家克星经典指标 大智慧经典指标 钱龙经典指标 同花顺经典指标 通达信经典指标 操盘手经典指标 期货特色指标 股票特色推荐 用户推荐共享指标 名家经典战法指标…...
springboot多实例部署时,@Scheduled注释的方法重复执行
问题:springboot多实例部署时,Scheduled注释的方法重复执行 在 Spring Boot 中要实现 Redis 的SET NX EX命令,可以借助 Spring Data Redis 来完成。SET NX EX命令用于在键不存在时设置键值对,并同时设置过期时间。 <dependen…...
智能自动化新纪元:AI与UiPath RPA的协同应用场景与技术实践
智能自动化新纪元:AI与UiPath RPA的协同应用场景与技术实践 引言 在数字化转型的浪潮中,企业对于自动化技术的需求已从简单的任务执行转向更复杂的智能决策。传统RPA(Robotic Process Automation)通过模拟人类操作处理重复性任务…...
[STM32 - 野火] - - - 固件库学习笔记 - - - 十六.在SRAM中调试代码
一、简介 在RAM中调试代码是一种常见的嵌入式开发技术,尤其适用于STM32等微控制器。它的核心思想是将程序代码和数据加载到微控制器的内部RAM(SRAM)中运行,而不是运行在Flash存储器中。这种方法在开发过程中具有显著的优势&#…...
nginx 反向代理 配置请求路由
nginx | 反向代理 | 配置请求路由 nginx简介 Nginx(发音为“Engine-X”)是一款高性能、开源的 Web 服务器和反向代理服务器,同时也支持邮件代理和负载均衡等功能。它由俄罗斯程序员伊戈尔西索夫(Igor Sysoev)于 2004…...
第二届粤港澳大湾区数字经济与人工智能国际学术会议(DEAI 2025)
重要信息 2025年3月28-30日 I 广东省东莞市(广东科技学院-松山湖校区) I www.icdeai.com 简介 第二届粤港澳大湾区数字经济与人工智能(DEAI 2025)将在2025年3月28-30日在广东省东莞市隆重举行。来自国内外高等院校、科学研究所、企事业单位的专家、教授、学者、…...
使用GDI+、文件和目录和打印API,批量将图片按文件名分组打包成PDF
代码写了两个小时,速度太慢(包括学习文档的时间) #include <stdio.h> #include <Windows.h> #include <gdiplus.h> #include <string.h> using namespace Gdiplus; #pragma comment(lib, "Gdiplus.lib") …...
贪心算法
int a[1000], b5, c8; swap(b, c); // 交换操作 memset(a, 0, sizeof(a)); // 初始化为0或-1 引导问题 为一个小老鼠准备了M磅的猫粮,准备去和看守仓库的猫做交易,因为仓库里有小老鼠喜欢吃的五香豆,第i个房间有J[i] 磅的五香豆…...
如何查询网站是否被百度蜘蛛收录?
一、使用site命令查询 这是最直接的方法。在百度搜索框中输入“site:你的网站域名”,例如“site:example.com”(请将“example.com”替换为你实际的网站域名)。如果搜索结果显示了你的网站页面,并且显示了收录的页面数量…...
Hutool - Log:自动识别日志实现的日志门面
一、简介 在 Java 开发中,日志记录是一项非常重要的功能,它可以帮助开发者在开发和生产环境中监控程序的运行状态、排查问题。然而,Java 生态系统中有多种日志实现框架,如 Log4j、Logback、JDK 自带的日志框架等。为了在不同的项…...
【GPU驱动】- 状态机
一、概述 Mesa 是一个开源的图形库,它提供了一个通用的图形抽象层,支持多种硬件和驱动程序。Mesa 的核心组件之一是 State Tracker,它在抽象图形 API(如 OpenGL )与具体的图形驱动之间起到桥梁作用。State Tracker 通…...
rtcwake - Linux下定时唤醒计算机
rtcwake 是一个用于通过实时时钟(RTC)唤醒计算机的工具。它常用于在 Linux 系统中设置计算机在指定时间自动唤醒或关闭。以下是对命令 rtcwake -m off -s ${sleep_time} 的详细解析: 命令解析 bash复制 rtcwake -m off -s ${sleep_time} 1…...
MySQL 日志
MySQL 日志 慢查询日志(Slow query log) 慢查询⽇志由执⾏时间超过系统变量 long_query_time 指定的秒数的SQL语句组成,并且检 查的⾏数⼤于系统变量 min_examined_row_limit 指定值。被记录的慢查询需要进⾏优化, 可以使⽤mysqldumpslow客⼾端程序对慢…...
C++ 泛型编程之补充(class 和typename)
目录 1.class 和 typename 可互换 1.1 template 和 template 在模板参数列表中完全一样,可以互换使用。 2.什么时候 class 和 typename 不一样? 2.1 嵌套依赖类型 时必须用typename 重点说明: 2.2 普通作用域(不能互换&…...
[MDM 2024]Spatial-Temporal Large Language Model for Traffic Prediction
论文网址:[2401.10134] Spatial-Temporal Large Language Model for Traffic Prediction 论文代码:GitHub - ChenxiLiu-HNU/ST-LLM: Official implementation of the paper "Spatial-Temporal Large Language Model for Traffic Prediction" …...
跟着 Lua 5.1 官方参考文档学习 Lua (6)
文章目录 2.11 – Coroutines 2.11 – Coroutines Lua supports coroutines, also called collaborative multithreading. A coroutine in Lua represents an independent thread of execution. Unlike threads in multithread systems, however, a coroutine only suspends i…...
Spring Cloud — Hystrix 服务隔离、请求缓存及合并
Hystrix 的核心是提供服务容错保护,防止任何单一依赖耗尽整个容器的全部用户线程。使用舱壁隔离模式,对资源或失败单元进行隔离,避免一个服务的失效导致整个系统垮掉(雪崩效应)。 1 Hystrix监控 Hystrix 提供了对服务…...
加油站(力扣134)
既然每一个加油站都有对应的加油量和耗油量,我们不妨计算一下每个加油站的汽油净增量。如果每个加油站净增量之和不为负数,则说明一定可以找到唯一的起始点。那我们该如何找到这个起始点呢?我们设置最开始的起点为第0个加油站,接着…...