学懂C++(三十):高级教程——深入解析 C++ Windows API 的多线程支持
引言
在现代应用程序中,多线程编程是实现高性能和高并发任务的关键手段。Windows 操作系统为开发者提供了一套强大的 API,用于创建和管理线程、同步任务,并优化线程性能。本文将深入探讨 C++ 中 Windows API 的多线程支持,详细介绍线程的创建与控制、线程优先级的设置、线程局部存储(TLS)、各种同步机制(如临界区、互斥体、信号量、事件)以及纤程(Fibers)的应用。
1. 线程的创建和控制
1.1 创建线程:CreateThread
CreateThread
是 Windows API 用于创建线程的函数。它允许程序在不同的并发路径上运行代码,从而提升应用程序的响应速度和处理能力。
示例:创建一个简单的线程
#include <windows.h>
#include <iostream>DWORD WINAPI ThreadFunc(LPVOID lpParam) {std::cout << "Thread is running." << std::endl;return 0;
}int main() {HANDLE hThread = CreateThread(nullptr, // 默认安全属性0, // 默认堆栈大小ThreadFunc, // 线程函数nullptr, // 线程函数参数0, // 默认创建标志nullptr // 不返回线程标识符);if (hThread) {WaitForSingleObject(hThread, INFINITE); // 等待线程完成CloseHandle(hThread); // 关闭线程句柄}return 0;
}
1.2 线程退出与终止:ExitThread
和 TerminateThread
ExitThread
:用于安全地退出线程。TerminateThread
:强制终止线程,但会导致资源泄漏,不推荐使用。
示例:使用 ExitThread
安全退出线程
#include <windows.h>
#include <iostream>DWORD WINAPI ThreadFunc(LPVOID lpParam) {std::cout << "Thread is running." << std::endl;ExitThread(0); // 安全退出线程
}int main() {HANDLE hThread = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);if (hThread) {WaitForSingleObject(hThread, INFINITE); // 等待线程完成CloseHandle(hThread); // 关闭线程句柄}return 0;
}
示例:使用 TerminateThread
强制终止线程(不推荐)
#include <windows.h>
#include <iostream>DWORD WINAPI ThreadFunc(LPVOID lpParam) {while (true) {std::cout << "Thread is running." << std::endl;Sleep(1000);}return 0;
}int main() {HANDLE hThread = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);if (hThread) {Sleep(3000); // 让线程运行一段时间TerminateThread(hThread, 0); // 强制终止线程(不推荐)CloseHandle(hThread); // 关闭线程句柄}return 0;
}
1.3 等待线程完成:WaitForSingleObject
和 WaitForMultipleObjects
WaitForSingleObject
:用于等待单个线程或同步对象的信号。WaitForMultipleObjects
:用于等待多个线程或同步对象的信号。
示例:使用 WaitForSingleObject
等待单个线程
#include <windows.h>
#include <iostream>DWORD WINAPI ThreadFunc(LPVOID lpParam) {Sleep(2000); // 模拟长时间运行的操作std::cout << "Thread completed." << std::endl;return 0;
}int main() {HANDLE hThread = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);if (hThread) {std::cout << "Waiting for thread to complete..." << std::endl;WaitForSingleObject(hThread, INFINITE); // 等待线程完成std::cout << "Thread has completed." << std::endl;CloseHandle(hThread); // 关闭线程句柄}return 0;
}
示例:使用 WaitForMultipleObjects
等待多个线程
#include <windows.h>
#include <iostream>DWORD WINAPI ThreadFunc(LPVOID lpParam) {Sleep(1000); // 模拟操作std::cout << "Thread " << *(int*)lpParam << " completed." << std::endl;return 0;
}int main() {HANDLE hThreads[2];int threadParams[2] = { 1, 2 };for (int i = 0; i < 2; i++) {hThreads[i] = CreateThread(nullptr, 0, ThreadFunc, &threadParams[i], 0, nullptr);}std::cout << "Waiting for threads to complete..." << std::endl;WaitForMultipleObjects(2, hThreads, TRUE, INFINITE); // 等待所有线程完成for (int i = 0; i < 2; i++) {CloseHandle(hThreads[i]); // 关闭线程句柄}std::cout << "All threads have completed." << std::endl;return 0;
}
2. 线程优先级
Windows 提供了丰富的 API 来控制线程的优先级,以便更好地管理线程的执行顺序。
2.1 设置线程优先级:SetThreadPriority
SetThreadPriority
允许开发者根据线程的重要性来调整其优先级,从而影响调度器对线程的调度频率。
示例:设置线程的优先级
#include <windows.h>
#include <iostream>DWORD WINAPI ThreadFunc(LPVOID lpParam) {std::cout << "Thread is running at priority: " << GetThreadPriority(GetCurrentThread()) << std::endl;return 0;
}int main() {HANDLE hThread = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);if (hThread) {SetThreadPriority(hThread, THREAD_PRIORITY_HIGHEST); // 设置线程优先级WaitForSingleObject(hThread, INFINITE);CloseHandle(hThread);}return 0;
}
2.2 获取线程优先级:GetThreadPriority
GetThreadPriority
用于获取当前线程的优先级,以便对线程的执行情况进行监控或调整。
示例:获取线程优先级
#include <windows.h>
#include <iostream>DWORD WINAPI ThreadFunc(LPVOID lpParam) {std::cout << "Thread is running at priority: " << GetThreadPriority(GetCurrentThread()) << std::endl;return 0;
}int main() {HANDLE hThread = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);if (hThread) {int priority = GetThreadPriority(hThread);std::cout << "Initial thread priority: " << priority << std::endl;SetThreadPriority(hThread, THREAD_PRIORITY_LOWEST); // 改变线程优先级priority = GetThreadPriority(hThread);std::cout << "Changed thread priority: " << priority << std::endl;WaitForSingleObject(hThread, INFINITE);CloseHandle(hThread);}return 0;
}
3. 线程局部存储(TLS)
线程局部存储(TLS)允许线程在其本地范围内存储和访问数据。每个线程都有独立的存储区域,不会与其他线程共享。
3.1 分配 TLS 索引:TlsAlloc
TlsAlloc
分配一个 TLS 索引,供后续在该索引上存取数据。
3.2 访问 TLS 数据:TlsGetValue
和 TlsSetValue
TlsGetValue
:从指定的 TLS 索引获取数据。TlsSetValue
:在指定的 TLS 索引上存储数据。
3.3 释放 TLS 索引:TlsFree
TlsFree
释放先前分配的 TLS 索引。
示例:使用 TLS 存储线程局部数据
#include <windows.h>
#include <iostream>DWORD tlsIndex;DWORD WINAPI ThreadFunc(LPVOID lpParam) {int localData = *(int*)lpParam; // 每个线程独立的数据TlsSetValue(tlsIndex, (LPVOID)&localData);int* pData = (int*)TlsGetValue(tlsIndex);std::cout << "Thread local data: " << *pData << std::endl;return 0;
}int main() {tlsIndex = TlsAlloc(); // 分配 TLS 索引if (tlsIndex == TLS_OUT_OF_INDEXES) {return 1;}int threadData[2] = { 10, 20 };HANDLE hThread1 = CreateThread(nullptr, 0, ThreadFunc, &threadData[0], 0, nullptr);HANDLE hThread2 = CreateThread(nullptr, 0, ThreadFunc, &threadData[1], 0, nullptr);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);CloseHandle(hThread1);CloseHandle(hThread2);TlsFree(tlsIndex); // 释放 TLS 索引return 0;
}
4. 同步机制
4.1 临界区(Critical Section)
临界区用于保护共享资源,防止多个线程同时访问同一资源。相比互斥体,临界区的性能更高,但只适用于单一进程内的线程同步。
InitializeCriticalSection
:初始化临界区。EnterCriticalSection
:进入临界区。LeaveCriticalSection
:离开临界区。DeleteCriticalSection
:删除临界区。
示例:使用临界区保护共享资源
#include <windows.h>
#include <iostream>CRITICAL_SECTION cs;
int counter = 0;DWORD WINAPI ThreadFunc(LPVOID lpParam) {for (int i = 0; i < 10000; ++i) {EnterCriticalSection(&cs);++counter;LeaveCriticalSection(&cs);}return 0;
}int main() {InitializeCriticalSection(&cs);HANDLE hThread1 = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);HANDLE hThread2 = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);std::cout << "Final counter value: " << counter << std::endl;CloseHandle(hThread1);CloseHandle(hThread2);DeleteCriticalSection(&cs);return 0;
}
4.2 互斥体(Mutex)
互斥体是用于多进程同步的对象。它比临界区更通用,但性能略低。
CreateMutex
:创建或打开一个命名的互斥体对象。ReleaseMutex
:释放互斥体。
示例:使用互斥体同步线程
#include <windows.h>
#include <iostream>HANDLE hMutex;DWORD WINAPI ThreadFunc(LPVOID lpParam) {WaitForSingleObject(hMutex, INFINITE); // 请求互斥体std::cout << "Thread running with mutex protection." << std::endl;Sleep(1000); // 模拟工作ReleaseMutex(hMutex); // 释放互斥体return 0;
}int main() {hMutex = CreateMutex(nullptr, FALSE, nullptr); // 创建互斥体HANDLE hThread1 = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);HANDLE hThread2 = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);std::cout << "Both threads have completed." << std::endl;CloseHandle(hThread1); // 关闭线程句柄CloseHandle(hThread2);CloseHandle(hMutex); // 关闭互斥体句柄return 0;
}
4.3 信号量(Semaphore)
信号量控制一组资源的访问权限,可以限制多个线程同时访问一个或多个资源。
CreateSemaphore
:创建信号量对象。ReleaseSemaphore
:释放信号量。
示例:使用信号量控制线程访问资源
#include <windows.h>
#include <iostream>HANDLE hSemaphore;DWORD WINAPI ThreadFunc(LPVOID lpParam) {WaitForSingleObject(hSemaphore, INFINITE); // 请求信号量std::cout << "Thread is accessing a limited resource." << std::endl;Sleep(1000); // 模拟工作ReleaseSemaphore(hSemaphore, 1, nullptr); // 释放信号量return 0;
}int main() {hSemaphore = CreateSemaphore(nullptr, 2, 2, nullptr); // 创建信号量,初始值和最大值均为2HANDLE hThread1 = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);HANDLE hThread2 = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);HANDLE hThread3 = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr); // 第三个线程将等待// 等待所有线程完成WaitForSingleObject(hThread1, INFINITE);WaitForSingleObject(hThread2, INFINITE);WaitForSingleObject(hThread3, INFINITE);std::cout << "All threads have completed." << std::endl;CloseHandle(hThread1);CloseHandle(hThread2);CloseHandle(hThread3);CloseHandle(hSemaphore); // 关闭信号量句柄return 0;
}
4.4 事件(Event)
事件对象用于线程之间的信号传递,允许一个线程通知一个或多个线程某个事件的发生。
CreateEvent
:创建事件对象。SetEvent
:设置事件为信号状态。ResetEvent
:将事件重置为非信号状态。
示例:使用事件同步线程
#include <windows.h>
#include <iostream>HANDLE hEvent;DWORD WINAPI ThreadFunc(LPVOID lpParam) {std::cout << "Thread waiting for event..." << std::endl;WaitForSingleObject(hEvent, INFINITE); // 等待事件被设置std::cout << "Thread proceeding after event!" << std::endl;return 0;
}int main() {hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr); // 创建手动重置事件HANDLE hThread = CreateThread(nullptr, 0, ThreadFunc, nullptr, 0, nullptr);if (hThread) {Sleep(2000); // 模拟一些工作std::cout << "Setting event." << std::endl;SetEvent(hEvent); // 释放线程WaitForSingleObject(hThread, INFINITE); // 等待线程完成CloseHandle(hThread);}CloseHandle(hEvent); // 关闭事件句柄return 0;
}
5. 纤程(Fibers)
纤程是比线程更轻量级的执行单元,允许程序在用户空间中管理调度。纤程的创建和切换比线程更快,适合某些特定的高性能应用。
5.1 纤程的基本操作
ConvertThreadToFiber
:将当前线程转换为纤程。CreateFiber
:创建纤程。SwitchToFiber
:切换到指定的纤程。DeleteFiber
:删除纤程。
示例:使用纤程
#include <windows.h>
#include <iostream>VOID CALLBACK FiberFunc(ULONG_PTR lpParam) {std::cout << "Fiber is running!" << std::endl;
}int main() {// 将主线程转换为纤程PVOID pFiber = ConvertThreadToFiber(nullptr);if (pFiber == nullptr) {std::cerr << "Failed to convert thread to fiber." << std::endl;return 1;}// 创建新的纤程PVOID pNewFiber = CreateFiber(0, FiberFunc, nullptr);if (pNewFiber == nullptr) {std::cerr << "Failed to create fiber." << std::endl;return 1;}// 切换到新的纤程SwitchToFiber(pNewFiber);// 切换回原纤程SwitchToFiber(pFiber);// 删除新创建的纤程DeleteFiber(pNewFiber);return 0;
}
6. 总结
通过以上内容,我们详细展示了 C++ 中 Windows API 的多线程支持,包括线程的创建、控制、优先级管理、线程局部存储、各种同步机制(临界区、互斥体、信号量、事件)以及纤程的使用。每个示例都展示了如何使用相关的 Windows API,帮助你加深理解和掌握多线程编程的技巧。希望这些示例能够帮助你在开发高性能和高并发的应用程序时更得心应手。通过掌握这些技术,开发者能够构建高效、稳定的多线程应用,充分利用现代硬件的并发能力,提升应用程序的性能。希望本文能够为 C++ 开发者提供有益的指导和实践经验,助力提升在 Windows 平台下的多线程编程能力。
上一篇:学懂C++(二十九):高级教程——深入解析 C++ 异步任务和 Futures:std::future、
下一篇:学懂C++(三十一):高级教程——深入详解C++高级多线程编程技术之锁优化与替代
相关文章:
学懂C++(三十):高级教程——深入解析 C++ Windows API 的多线程支持
引言 在现代应用程序中,多线程编程是实现高性能和高并发任务的关键手段。Windows 操作系统为开发者提供了一套强大的 API,用于创建和管理线程、同步任务,并优化线程性能。本文将深入探讨 C 中 Windows API 的多线程支持,详细介绍线…...
苹果笔记本电脑可以玩steam游戏吗 MacBook支持玩steam游戏吗 在Steam上玩黑神话悟空3A大作 苹果Mac怎么下载steam
游戏是生活的润滑剂,越来越多的用户开始关注Mac平台上可玩的游戏。幸运的是,Steam作为最大的数字发行平台之一,提供了大量适用于Mac操作系统的游戏。无论你是喜欢策略、冒险还是射击类游戏,都能在Steam上找到适合自己Mac设备玩耍的…...
海康摄像头(测温型)桌面客户端开发分享
分享一个自己开发的用于企业特殊场景下温度监控告警的一个桌面应用。 关键功能: 1.支持海康摄像头; 2.支持多路视频预览,多通道画面选择预览,支持视频画面回放与下载; 3.支持自动探测摄像头功能,若具备…...
骑行耳机哪个品牌性价比高?精选五大畅销骑行耳机推荐!
骨传导耳机凭借不入耳佩戴更舒适、健康等特定在短时间内迅速风靡骑行圈,其独特的设计不仅让骑行者在享受音乐的同时保持对周围环境的警觉,还因其非入耳式的佩戴方式,有效避免了长时间骑行对耳朵的压迫与不适。它不仅能够激发骑行时的激情与动…...
libcurl8.9.1 上传json
在postman中 PUT----》body----》raw----》json 结构体定义: #define MAX_ARRAY_SIZE 5*1024*1024struct SMART_DATA_CACHE {char* buf;long dwTotalLen;SMART_DATA_CACHE(){dwTotalLen 0;buf nullptr;while (!buf) {try {buf new char[MAX_ARRAY_SIZE];}c…...
什么是暗水印?企业暗水印如何实施?企业保护利器
“明察秋毫之末,而不见舆薪。” 此言道出了观察之细致入微,却也隐含了信息泄露之隐忧。 在今日之数字时代,信息如潮水般汹涌,而电脑屏幕作为信息展示的重要窗口,其安全性亦成为众人关注的焦点。 当谈及监控电脑屏幕以…...
Qt 系统相关 - 文件
目录 1. 文件概述 2. 输入输出设备类 3. 文件读写类 4. 文件和目录信息类 1. 文件概述 文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库,提供了跨平台的文件操作能力。 Qt 提供了很多关于文件的类,通过这些类能够对文件系统进行操作&#x…...
Android Toast居中显示方法二
Android Toast居中显示方法一请看 Android Toast设置居中显示方法一-CSDN博客 下面来讲讲第二种方法: Toast toast Toast.makeText(MainActivity.this, "my toast", Toast.LENGTH_SHORT);LinearLayout.LayoutParams layoutParams new LinearLayout.Lay…...
Vue启动时报异常 ‘error:03000086:digital envelope routines::initialization error‘
问题描述 启动Vue项目时,突发报如下异常: opensslErrorStack: [error:03000086:digital envelope routines::initialization error,error:0308010C:digital envelope routines::unsupported],library: digital envelope routines,reason: unsupported,…...
C#委托—马工教你轻松玩转委托
前言 在C#中有一个小白谈之色变的知识点叫委托,很多学了一两年C#的还不知道委托究竟是什么东西,本文就来帮你彻底解开解惑,从此委托就是小儿科! 1、委托的本质 委托也是一种类型,大家知道所有的类型一定对应一种数据…...
当下最强的 AI art 生成模型 Stable Diffusion 最全面介绍
目录 模型生成效果展示(prompt 全公开) 如何注册 Stable Diffusion 使用 SD(dreamstudio.ai )的收费标注如何 SD 提供哪些参数可以设置 如何使用种子来改进一张作品 我用 SD 创作的图片著作权如何归属,可以拿来商…...
NPM 使用教程:从入门到精通
NPM 使用教程:从入门到精通 1. 引言 什么是 NPM? NPM (Node Package Manager) 是 JavaScript 的包管理工具,也是世界上最大的开源库生态系统。它帮助开发者轻松地管理项目的依赖、安装和分享包。NPM 与 Node.js 紧密结合,并在开…...
基于ssm+vue+uniapp的停车场小程序的设计与实现
开发语言:Java框架:ssmuniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:M…...
C语言典型例题37
《C程序设计教程(第四版)——谭浩强》 例题3.5 按照按照考试成绩的等级输出百分制分数段,A等为85分以上,B等为70~84分,C等为 60~69分,D等在60分以下,成绩的等级从键盘输入 代码: //…...
二自由度机械臂软件系统(三)ros2_control硬件底层插件
ros2_control实现了两个功能,一个是控制算法插件即控制的实现,另一个是底层插件即跟硬件通信的功能。 参考资料:https://zhuanlan.zhihu.com/p/682574842 1、创建功能包 ros2 pkg create --build-type ament_cmake robot_control_test在sr…...
24.8.9.11数据结构|链栈和队列
链栈 1、理解 实际上是一个仅在表头进行操作的单链表,头指针指向栈顶结点或头结点,以下恋栈均指带头结点的链栈. 2、 基本操作 1、定义结构:节点含有数据域和指针域 2、初始化操作:建立一个带头结点的空栈 3、取栈顶元素操作:取出栈的栈顶元…...
StarSpider:一款高效的网络爬虫框架解析与实战
文章目录 引言官网链接StarSpider 原理简介基础使用1. 添加依赖2. 编写PageProcessor3. 启动爬虫 高级使用1. 分布式抓取2. 自定义下载器3. 深度定制 优点结语 引言 在大数据时代,数据成为了推动业务增长和创新的关键。网络爬虫作为数据获取的重要手段之一…...
LVS详细解析及其NAT模式与DR模式部署(理论+实验全方位指导)
目录 1. 集群 2. 分布式系统 3. 集群与分布式的比较 4.通俗的解释 集群 分布式系统 总结 LVS(Linux Virtual Server)简介 LVS专业术语 工作原理 LVS调度算法 静态调度算法 动态调度算法 ipvsadm脑图 NAT模式集群 LVS的配置 在LVS主机内打开…...
负载均衡相关概念介绍(一)
负载均衡(Load Balance)是集群技术的一种重要应用,旨在将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,从而提高系统的并发处理能力、增加吞吐量、加强网络处理能力,并提供故障转移以…...
二叉树详解(1)
文章目录 目录1. 树的概念及结构1.1 树的相关概念1.2 树的表示1.3 树在实际中的运用(表示文件系统的目录树结构) 2. 二叉树的概念及结构2.1 概念2.2 特殊的二叉树2.3 二叉树的存储结构 3. 二叉树的顺序结构及实现3.1 二叉树的顺序结构3.2 堆的概念及结构…...
Spring定时任务注解
Service EnableScheduling public class xxxServiceImpl implement xxxService{Scheduled(cron "0 15 11 * * ?") // 每天的11:15执行public void reportCurrentTime() {aaa();}Scheduled(cron "0 15 17 * * ?") // 每天的17:15执行public void report…...
数据结构-绪论
学习目标: 认识数据结构的基本内容 学习内容: 了解:数据结构的研究内容掌握:数据结构的基本概念和术语了解:数据元素间的结构关系掌握:算法及算法的描述 数据结构的发展: 数据结构的发展简史 …...
Web开发:web服务器-Nginx的基础介绍(含AI文稿)
目录 一、Nginx的功能: 二、正向代理和反向代理的区别 三、Nginx负载均衡的主要功能 四、nginx安装目录下的各个文件(夹)的作用: 五、常用命令 一、Nginx的功能: 1.反向代理:例如我有三台服务器&#x…...
共享经济背景下校园、办公闲置物品交易平台-计算机毕设Java|springboot实战项目
🍊作者:计算机毕设残哥 🍊简介:毕业后就一直专业从事计算机软件程序开发,至今也有8年工作经验。擅长Java、Python、微信小程序、安卓、大数据、PHP、.NET|C#、Golang等。 擅长:按照需求定制化开发项目、 源…...
Linux 服务器上简单配置 minio
Linux 服务器上简单配置 minio 初始化结构目录 mkdir -p /data/minio/bin mkdir -p /data/minio/conf mkdir -p /data/minio/data 下载 minio cd /data/minio/bin curl -O https://dl.min.io/server/minio/release/linux-amd64/minio 添加执行权限 chmod x minio 创建配置文件…...
TypeScript 面试题汇总
引言 TypeScript 是一种由微软开发的开源、跨平台的编程语言,它是 JavaScript 的超集,为 JavaScript 添加了静态类型系统和其他高级功能。随着 TypeScript 在前端开发领域的广泛应用,掌握 TypeScript 已经成为很多开发者必备的技能之一。本文…...
杰卡德系数
杰卡德系数(Jaccard Index 或 Jaccard Similarity Coefficient) 杰卡德系数是一种用于衡量两个集合相似度的重要指标。 从数学定义上来看,如前面所述,杰卡德系数计算公式为: J ( A , B ) ∣ A ∩ B ∣ ∣ A ∪ B ∣…...
微服务实现-sleuth+zipkin分布式链路追踪和nacos配置中心
1. sleuthzipkin分布式链路追踪 在大型系统的微服务化构建中,一个系统被拆分成了许多微服务。这些模块负责不同的功能,组合成系统,最终可以提供丰富的功能。 这种架构中,一次请求往往需要涉及到多个服务。互联网应用构建在不同的软…...
数学中常用的解题方法
文章目录 待定系数法应用示例1. 多项式除法2. 分式化简3. 数列通项公式 总结 递归数列特征方程特征根的求解通项公式的求解示例 错位相减,差分错位相减法差分的应用结合理解 韦达定理二项式定理二项式定理的通项公式二项式系数的性质应用示例 一元二次求解1. 因式分…...
pytorch 1 张量
张量 文章目录 张量torch.Tensor 的 主要属性torch.Tensor 的 其他常用属性和方法叶子张量(Leaf Tensors)定义叶子张量的约定深入理解示例代码总结 中间计算结果与 detach() 方法定义中间计算结果不是叶子节点使用 detach() 方法使中间结果成为叶子张量示…...
北京网站建设 标准型 新翼/建设网页
分布式编程模型的背景 编程模型是指编程的方法而不是特指某一种编程语言,如面向对象的编程就是一种编程模型。编程模型大致分为两类:命令式编程和声明式编程。前者最典型的是面向过程的编程语言,如C语言;后者与前者差异较大&#…...
社区平安建设基层网站/上海seo培训中心
ES安装及head插件安装1.官网下载2.windows下安装3.如果内存小 修改配置文件jvm.options启动参数4.启动 双击elasticsearch.bat5.访问 127.0.0.1:92006.安装可视化界面 以及启动7.解决跨域问题8.再次启动elasticsearch-head-master 访问http://localhost:9100/总结JDK1.8 &#…...
网站建站的标准/重庆seo网页优化
1、Base64编码介绍Base64不能称为加解密算法,Base64编码可以把二进制数据转换为可打印的ASCII字符,常用于email消息中的二进制数据编码和HTTP协议中的basic认证。Base64编码之后的ASCII字符串包括64个可打印字符,如下:26个大写字母…...
游戏网站的设计/百度下载并安装
linux 后台启动java的命令一例 查看已启动的进程实例命令: ps -aux|grep java启动java的进程实例命令: java -jar cloud-auth-1.0.jarjava -cp cloud-eureka-1.0-exec.jar:lib/*:./config/application.yml com.yzh.cloud.eureka.EurekaApplication后…...
做网站主要学什么条件/测试自己适不适合做销售
本文讲的是域渗透提权分析工具 BloodHound 1.3 中的ACL攻击路径介绍,简介和背景2014年,Emmanuel Gras和Lucas Bouillot在“ 信息通信技术研讨会”(Symposium on Information and Communications)上发表了题为“ Chemins decontrle…...
甘肃省住房建设厅网站/武汉网站建设优化
目前为止,普通用户只能通过下载Firefoxos Rom刷到自己的android手机上才能进行真实的手机设备端的体验。不过近日,传mozilla已经制造了首批原生搭载firefox os的手机设备,以方便用户和开发者对火狐OS进行更好的评估和协助项目的开发。目前此款…...