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

【C++】多线程

目录

一 概念

1 多线程

2 多进程与多线程

3 多线程理解

二 创建线程

1 thread

2 join() 和 detach()

3 this_thread

三 std::mutex

1 lock 和 unlock

2 lock_guard

3 unique_lock 

四 condition_variable

五 std::atomic


一 概念

1 多线程

在C++11之前,涉及到多线程问题,都是和平台相关的,比如windows和linux下各有自己的接 口,这使得代码的可移植性比较差。C++11中最重要的特性就是对线程进行支持了,使得C++在 并行编程时不需要依赖第三方库,而且在原子操作中还引入了原子类的概念。要使用标准库中的 线程,必须包含< thread >头文件.

C++11引入了对多线程编程的支持,主要提供了以下几个组件:

  1. std::thread类:用于创建和管理线程的对象。
  2. std::mutex类:用于实现互斥访问,保护共享资源的完整性。
  3. std::condition_variable类:用于线程间的条件同步。
  4. std::atomic模板类:用于实现原子操作,确保数据的原子性

2 多进程与多线程

进程是指一个程序的运行实例,而线程是指进程中独立的执行流程。一个进程可以有多个线程,多个线程之间可以并发执行。

  • 一个程序有且只有一个进程,但可以拥有至少一个的线程。
  • 不同进程拥有不同的地址空间,互不相关,而不同线程共同拥有相同进程的地址空间。

创建一个新线程的代价要比创建一个新进程小得多 与进程之间的切换相比,线程之间的切换需要操作系统做的工作要少很多 线程占用的资源要比进程少很多

3 多线程理解

二 创建线程

1. 线程是操作系统中的一个概念,线程对象可以关联一个线程,用来控制线程以及获取线程的 状态。

2. 当创建一个线程对象后,没有提供线程函数,该对象实际没有对应任何线程。

3. C++支持多线程编程,主要使用的是线程库<thread>

1 thread

示例1: 线程函数(函数指针)

#include<iostream>
#include<thread>
using namespace std;void Print1(int n, int j)
{cout << "n: " << n << " j: " << j << endl;
}void Print2()
{cout << "Test2" << endl;
}int main()
{// 线程函数为函数指针thread t1(Print1, 100, 5);thread t2(Print2);t1.join();t2.join();return 0;
}

上述示例中,我们创建了两个线程t1t2,使用函数Print1()和Print2()作为线程的执行函数,并使用join()函数等待线程执行完成。 

示例2: 执行函数有引用参数

void Print(int n, int& rx)
{rx += n;cout << "Test: " << rx << endl;
}int main()
{int x = 0;thread t1(Print, 10000, ref(x));// 只有添加 ref 才能会被底层认为是引用thread t2(Print, 20000, ref(x));t1.join();t2.join();cout << x << endl;return 0;
}

  • std::ref 可以包装按引用传递的值为右值。
  • std::cref 可以包装按const引用传递的值为右值。

 示例3: lambda 表达式

int main()
{int x = 0;auto Func = [&](int n){x += n;};thread t1(Func, 10000);thread t2(Func, 20000);t1.join();t2.join();cout << x << endl;return 0;
}

2 join() 和 detach()

当线程启动后,一定要在和线程相关联的thread销毁前,确定以何种方式等待线程执行结束。比如上例中的join。

  • detach方式,启动的线程自主在后台运行,当前的代码继续往下执行,不等待新线程结束。
  • join方式,等待启动的线程完成,才会继续往下执行。

 示例1: join

oin后面的代码不会被执行,除非子线程结束

void thread_1()
{while (1){}
}
void thread_2(int x)
{while (1){}
}
int main()
{thread first(thread_1); // 开启线程,调用:thread_1()thread second(thread_2, 100); // 开启线程,调用:thread_2(100)first.join();second.join(); //join完了之后,才能往下执行。while (1){std::cout << "主线程\n";}return 0;
}

示例2: detach

 主线程不会等待子线程结束。如果主线程运行结束,程序则结束。

void thread_1()
{while (1){cout << "子线程1" << endl;}
}void thread_2(int x)
{while (1){cout << "子线程2" << endl;}
}int main()
{thread first(thread_1);  // 开启线程,调用:thread_1()thread second(thread_2, 100); // 开启线程,调用:thread_2(100)first.detach();second.detach();for (int i = 0; i < 10; i++){std::cout << "主线程\n";}return 0;

注意:

1. 线程是在thread对象被定义的时候开始执行的,而不是在调用join()函数时才执行的,调用join()函数只是阻塞等待线程结束并回收资源。
2. 分离的线程(执行过detach()的线程)会在调用它的线程结束或自己结束时自动释放资源。
3. 线程会在函数运行完毕后自动释放,不推荐利用其他方法强制结束线程,可能会因资源未释放而导致内存泄漏。
4. 若没有执行join()或detach()的线程在程序结束时会引发异常

3 this_thread

this_thread是一个类,它有4个功能函数,具体如下:

 此外,this_thread还包含重载运算符==!=,用于比较两个线程是否相等。

void my_thread()
{std::cout << "Thread " << std::this_thread::get_id() << " start!" << std::endl;std::this_thread::yield();	// 让出当前线程的时间片std::this_thread::sleep_for(std::chrono::milliseconds(200));  // 线程休眠200毫秒std::cout << "Thread " << std::this_thread::get_id() << " end!" << std::endl;
}int main()
{std::cout << "Main thread id: " << std::this_thread::get_id() << std::endl;std::thread t1(my_thread);std::thread t2(my_thread);t1.join();t2.join();return 0;
}

thread类是防拷贝的,不允许拷贝构造以及赋值,但是可以移动构造和移动赋值,即将一个 线程对象关联线程的状态转移给其他线程对象,转移期间不意向线程的执行。

可以通过jionable()函数判断线程是否是有效的,如果是以下任意情况,则线程无效

a 采用无参构造函数构造的线程对象  b 线程对象的状态已经转移给其他线程对象  c 线程已经调用jion或者detach结束

 并发与并行的区别?

并发和并行都可以是调用了很多线程. 如果这些线程能同时被多个处理器执行,那就是并行的;如果是轮流切换执行,那就是并发.

三 std::mutex

在多线程编程中,需要注意以下问题:

  • 线程之间的共享数据访问需要进行同步,以防止数据竞争和其他问题。可以使用互斥量条件变量等机制进行同步。
  • 可能会发生死锁问题,即多个线程互相等待对方释放锁,导致程序无法继续执行。
  • 可能会发生竞态条件问题,即多个线程执行的顺序导致结果的不确定性。

mutex头文件主要声明了与互斥量(mutex)相关的类。mutex提供了4种互斥类型,如下表所示。

1 lock 和 unlock

std::mutex是 C++11 中最基本的互斥量,一个线程将mutex锁住时,其它的线程就不能操作mutex,直到这个线程将mutex解锁。

 示例1: 

#include <mutex>std::mutex mtx;
int num = 0;void thread_func(int& n)
{for (int i = 0; i < 10; ++i){mtx.lock();n++;cout << "n: " << n << endl;;mtx.unlock();}
}int main()
{std::thread myThread[10];for (std::thread& a : myThread){a = std::thread(thread_func, std::ref(num));a.join();}std::cout << "num = " << num << std::endl;std::cout << "Main thread exits!" << std::endl;return 0;
}

2 lock_guard

std::lock_guard是C++标准库中的一个模板类,用于实现资源的自动加锁和解锁。它是基于RAII的设计理念,能够确保在作用域结束时自动释放锁资源,避免了手动管理锁的复杂性和可能出现的错误。

std::lock_guard的主要特点如下:

1 自动加锁: 在创建std::lock_guard对象时,会立即对指定的互斥量进行加锁操作。这样可以确保在进入作用域后,互斥量已经被锁定,避免了并发访问资源的竞争条件。
2 自动解锁:std::lock_guard对象在作用域结束时,会自动释放互斥量。无论作用域是通过正常的流程结束、异常抛出还是使用return语句提前返回,std::lock_guard都能保证互斥量被正确解锁,避免了资源泄漏和死锁的风险。
3 适用于局部锁定: 由于std::lock_guard是通过栈上的对象实现的,因此适用于在局部范围内锁定互斥量。当超出std::lock_guard对象的作用域时,互斥量会自动解锁,释放控制权。

#include <mutex>std::mutex mtx;  
int num = 0;
void thread_func(int& n)
{std::lock_guard<std::mutex> lock(mtx);  // 加锁互斥量std::cout << "n: " << n++ << std::endl;// 执行需要加锁保护的代码
}  int main()
{std::thread myThread[10];for (std::thread& a : myThread){a = std::thread(thread_func, std::ref(num));a.join();}std::cout << "num == " << num << std::endl;return 0;
}

3 unique_lock 

std::unique_lock的主要特点如下:

  • 自动加锁和解锁: 与std::lock_guard类似,std::unique_lock在创建对象时立即对指定的互斥量进行加锁操作,确保互斥量被锁定。在对象的生命周期结束时,会自动解锁互斥量。这种自动加锁和解锁的机制避免了手动管理锁的复杂性和可能出现的错误。
  • 支持灵活的加锁和解锁: 相对于std::lock_guard的自动加锁和解锁,std::unique_lock提供了更灵活的方式。它可以在需要的时候手动加锁和解锁互斥量,允许在不同的代码块中对互斥量进行多次加锁和解锁操作。
  • 支持延迟加锁和条件变量:std::unique_lock还支持延迟加锁的功能,可以在不立即加锁的情况下创建对象,稍后根据需要进行加锁操作。此外,它还可以与条件变量(std::condition_variable)一起使用,实现更复杂的线程同步和等待机制。
#include <mutex>std::mutex mtx;  // 互斥量void thread_function()
{std::unique_lock<std::mutex> lock(mtx);  // 加锁互斥量std::cout << "Thread running" << std::endl;// 执行需要加锁保护的代码lock.unlock();  // 手动解锁互斥量// 执行不需要加锁保护的代码lock.lock();  // 再次加锁互斥量// 执行需要加锁保护的代码
}
// unique_lock对象的析构函数自动解锁互斥量int main()
{std::thread t1(thread_function);t1.join();std::cout << "Main thread exits!" << std::endl;return 0;
}

在上述示例中,std::unique_lock对象lock会在创建时自动加锁互斥量,析构时自动解锁互斥量。我们可以通过调用lockunlock函数手动控制加锁和解锁的时机,以实现更灵活的操作。

四 condition_variable

std::condition_variable是C++标准库中的一个类,用于在多线程编程中实现线程间的条件变量和线程同步。它提供了等待通知的机制,使得线程可以等待某个条件成立时被唤醒,或者在满足某个条件时通知其他等待的线程。其提供了以下几个函数用于等待和通知线程:

 

std::condition_variable的主要特点如下:

  • 等待和通知机制:std::condition_variable允许线程进入等待状态,直到某个条件满足时才被唤醒。线程可以调用wait函数进入等待状态,并指定一个互斥量作为参数,以确保线程在等待期间互斥量被锁定。当其他线程满足条件并调用notify_one或notify_all函数时,等待的线程将被唤醒并继续执行。
  • 与互斥量配合使用:std::condition_variable需要与互斥量(std::mutex或std::unique_lock<std::mutex>)配合使用,以确保线程之间的互斥性。在等待之前,线程必须先锁定互斥量,以避免竞争条件。当条件满足时,通知其他等待的线程之前,必须再次锁定互斥量。
  • 支持超时等待:std::condition_variable提供了带有超时参数的等待函数wait_for和wait_until,允许线程在等待一段时间后自动被唤醒。这对于处理超时情况或限时等待非常有用。

示例:支持两个线程交替打印,一个打印奇数,一个打印偶数, 并且偶数优先

#include <thread>
#include <mutex>
#include <condition_variable>int main()
{std::mutex mtx;condition_variable c;int n = 100;bool flag = true;thread t1([&]() {int i = 0;while (i < n){unique_lock<mutex> lock(mtx);while (!flag)c.wait(lock);cout << i << endl;flag = false;i += 2; // 偶数c.notify_one();}});thread t2([&]() {int j = 1;while (j < n){unique_lock<mutex> lock(mtx);while (flag)c.wait(lock);cout << j << endl;j += 2; // 奇数flag = true;c.notify_one();}});t1.join();t2.join();return 0;
}

五 std::atomic

std::mutex可以很好地解决多线程资源争抢的问题,但它每次循环都要加锁、解锁,这样固然会浪费很多的时间。

在 C++ 中,std::atomic 是用来提供原子操作的类,atomic,本意为原子,原子操作是最小的且不可并行化的操作。这就意味着即使是多线程,也要像同步进行一样同步操作原子对象,从而省去了互斥量上锁、解锁的时间消耗。

使用 std::atomic 可以保证数据在操作期间不被其他线程修改,这样就避免了数据竞争,使得程序在多线程并发访问时仍然能够正确执行。

示例:

#include<vector>
#include <atomic>int main()
{atomic<int> x = 0;//不用加锁了auto Func = [&](int n){for (int i = 0; i < n; i++){x++;}};int n;cin >> n;vector<thread> vthds(n);for (auto& thd : vthds){thd = thread(Func, 10);}for (auto& thd : vthds){thd.join();}cout << x << endl;return 0;
}

总结: C++ 多线程基础就是这些, 难度不大, 重在理解,  但是要注意线程安全, 合理使用. 继续加油! 

相关文章:

【C++】多线程

目录 一 概念 1 多线程 2 多进程与多线程 3 多线程理解 二 创建线程 1 thread 2 join() 和 detach() 3 this_thread 三 std::mutex 1 lock 和 unlock 2 lock_guard 3 unique_lock 四 condition_variable 五 std::atomic 一 概念 1 多线程 在C11之前&#xff0…...

【计算机网络】实验2:总线型以太网的特性

实验 2&#xff1a;总线型以太网的特性 一、 实验目的 加深对MAC地址&#xff0c;IP地址&#xff0c;ARP协议的理解。 了解总线型以太网的特性&#xff08;广播&#xff0c;竞争总线&#xff0c;冲突&#xff09;。 二、 实验环境 • Cisco Packet Tracer 模拟器 三、 实…...

基于Matlab合成孔径雷达(SAR)回波信号建模与多指标质量评估

本研究基于合成孔径雷达&#xff08;SAR&#xff09;技术&#xff0c;建立了一个雷达回波信号的模拟模型&#xff0c;并通过多项评价指标对信号质量进行深入评估。首先&#xff0c;研究定义了与SAR系统相关的关键物理参数&#xff0c;如工作频率、平台速度、脉冲宽度、采样率等…...

spring boot3.3.5 logback-spring.xml 配置

新建 resources/logback-spring.xml 控制台输出颜色有点花 可以自己更改 <?xml version"1.0" encoding"UTF-8"?> <!--关闭文件扫描 scanfalse --> <configuration debug"false" scan"false"><springProperty …...

浅谈C#库之DevExpress

一、DevExpress库介绍 DevExpress是一个功能强大、界面美观的UI组件库&#xff0c;广泛应用于桌面应用程序和Web应用程序的开发中。它提供了丰富的控件和工具&#xff0c;帮助开发人员快速构建现代化的用户界面。DevExpress控件库以其功能丰富、应用简便、界面华丽以及方便定制…...

【webApp之h5端实战】项目基础结构搭建及欢迎页面的实现

这是一个实战项目的webapp,主要是使用原生js/css/html来实现我们的业务。预览下面的实战效果,我们将会从0到1实现这个系列的项目。包括大量的原生js知识,css3动画的开发,以及页面的交互实现。 效果预览 项目准备工作 封装的工具类,用于获取原生dom节点,处理原生dom事件的…...

生成树详解(STP、RSTP、MSTP)

目录 1、STP 1.概述 2.基本概念 3.端口角色及其作用 4.报文结构 5.STP的端口状态 6.三种定时器 7.STP选举步骤 8.配置BPDU的比较原则 9.TCN BPDU 10.临时环路的问题 11.传统STP的不足 拓扑变更处理过程 2、RSTP 1.端口角色 2.端口状态 3.P/A&#xff08;Propo…...

C++趣味编程:基于树莓派Pico的模拟沙漏-倾斜开关与LED的互动实现

沙漏,作为一种古老的计时工具,利用重力让沙子通过狭小通道,形成了计时效果。在现代,我们可以通过电子元件模拟沙漏的工作原理。本项目利用树莓派Pico、倾斜开关和LED,实现了一个电子沙漏。以下是项目的详细技术解析与C++代码实现。 一、项目概述 1. 项目目标 通过倾斜开关…...

Matlab Simulink 电力电子仿真-单相电压型半桥逆变电路分析

目录 一、单相电压型半桥逆变电路仿真模型 1.电路模型 2.电路模型参数 二、仿真分析 三、总结 1.优缺点 2.应用场景 一、单相电压型半桥逆变电路仿真模型 1.电路模型 单相电压型半桥逆变电路是一种常见的逆变电路&#xff0c;主要用于将直流电源转换为交流电源。 &…...

在超表面中琼斯矩阵的使用

琼斯矩阵&#xff08;Jones Matrix&#xff09; 是一种线性代数方法&#xff0c;用于描述光的偏振状态和偏振变化&#xff0c;是偏振光学中重要的数学工具。它在 超表面理论设计 中广泛应用&#xff0c;尤其是在设计和调控光与物质相互作用时&#xff0c;例如偏振控制、相位调制…...

threeJs学习 贴图 :地球

效果图&#xff1a; 贴图以后的效果&#xff1a; vue代码&#xff1a; <template><div class"scene_box"><p>创建纹理贴图TextureLoader</p><div class"canvas"></div></div> </template><script s…...

详解Rust多线程编程

文章目录 多线程模型创建和管理线程自定义线程行为线程传递数据线程间通信线程池错误处理与线程Condvar(条件变量)无锁并发高性能并发库 Rust的多线程编程提供了一种安全、高效的方式来进行并发操作。Rust的并发性设计原则之一是确保线程安全&#xff0c;同时避免运行时的开销&…...

Uniapp触底刷新

在你的代码中&#xff0c;使用了 scroll-view 来实现一个可滚动的评论区域&#xff0c;并且通过监听 scrolltolower 事件来触发 handleScrollToLower 函数&#xff0c;以实现“触底更新”或加载更多评论的功能。 关键部分分析&#xff1a; scroll-view 组件: scroll-view 是一…...

【前端】安装hadoop后,前端启动报错,yarn命令

新安装hadoop后&#xff0c;前端启动项目用yarn命令&#xff0c;报错。 报错&#xff1a;系统找不到指定的路径。 No HADOOP_CONF_DIR set. Please specify it either in yarn-env.cmd or in the environment. 解决&#xff1a;删掉hadoop目录下yarn的文件 检查&#xff1a;…...

T620存储安全方案SoC芯片技术手册

系统资源 集成32位国产CPU CK803S&#xff1b;最高工作频率260Mhz CK803S内置16KB I/D Cache&#xff0c;内置32KB DTCM 32KB ROM&#xff1b;256KB SRAM&#xff1b;8KB SRAM&#xff08;系统专用&#xff09; 512KB/1MB 片内Flash 安全算法 支持SM4数据加密&#xff0c;加密性…...

Rust循环引用与多线程并发

循环引用与自引用 循环引用的概念 循环引用指的是两个或多个对象之间相互持有对方的引用。在 Rust 中&#xff0c;由于所有权和生命周期的严格约束&#xff0c;直接创建循环引用通常会导致编译失败。例如&#xff1a; // 错误的循环引用示例 struct Node {next: Option<B…...

力扣 二叉树的锯齿形层序遍历-103

二叉树的锯齿形层序遍历-103 此题就是再二叉树层序遍历的基础上&#xff0c;加了反转当前层数组元素的函数reverse()&#xff0c;也可以不反转&#xff0c;直接在遍历当前层的所有节点的for循环里直接进行if判断&#xff0c;根据遍历方向&#xff0c;决定如何插入元素。 clas…...

PyCryptodome:Python中的密码学库

简介 PyCryptodome是一个功能强大的Python密码学库&#xff0c;提供了各种密码学算法的实现&#xff0c;包括对称加密、非对称加密、哈希函数、消息认证码等。它是对Python的Crypto库的一个现代化和增强版&#xff0c;提供了更好的性能和安全性。 Git地址 PyCryptodome的代码可…...

我眼中的“懂重构”(一)

初识重构 2017年的时候&#xff0c;领导让我看公司的一本书《重构——改善代码的既有设计》&#xff0c;这是一本JAVA版本的&#xff0c;前后看了2遍。那时候看书因为不懂看的格外仔细。我只是那时候不懂&#xff0c;然而多年后的今天我仍然发现很多人对重构充满误解。在刚进入…...

Excel中日期格式“年月日 时间”修改为“年月日”

需求&#xff1a; 将Excel中“yyyy-mm-dd hh:mm:ss”格式的时间转换为“yyyy-mm-dd”格式的时间&#xff0c;选中转换后的时间时编辑栏中依然会显示“yyyy-mm-dd hh:mm:ss”格式。 方法一、在原数据列进行转换&#xff1a; 1、选中需要转换的数据列&#xff0c;右键--【设置…...

CSS底层基础:小白速来

1. CSS简介 CSS (Cascading Style Sheets) 是一种用来描述HTML或XML文档样式的语言。它使得开发者能够控制网页的布局和外观&#xff0c;包括字体、颜色、间距等。CSS通过选择器来指定要应用样式的元素&#xff0c;并定义这些元素的具体样式属性。 基本结构示例&#xff1a; …...

【MySQL】库和表的基本操作

目录 库 库的增删查改 字符集与校验集 库的备份与恢复 表 表的创建和删除 用不同的存储引擎创建表的区别 查看表 修改表 添加删除属性 修改改变属性 上篇博客我们讲了数据库的基本理解&#xff0c;对数据库有了一个大致的概念&#xff0c;下面我们来介绍一下库和表的…...

5款AI智能办公工具丨提升办公效率‼️

办公效率低&#xff1f;工作压力大&#xff1f;别担心&#xff0c;这里有五款超实用的AI办公工具&#xff0c;帮你轻松搞定各种任务&#xff01;&#x1f31f; 简直不要太实用&#xff0c;快快收藏起来总有一天你会用得上~ 红薯通AI&#x1f4dd;写作文案的好帮手&#xff0c…...

华为HarmonyOS 让应用快速拥有账号能力 -- 3 获取用户手机号

场景介绍 当应用对获取的手机号时效性要求不高时&#xff0c;可使用Account Kit提供的手机号授权与快速验证能力&#xff0c;向用户发起手机号授权申请&#xff0c;经用户同意授权后&#xff0c;获取到手机号并为用户提供相应服务。以下只针对Account kit提供的手机号授权与快…...

lambda strem流表达式处理工具

一个通用的lambda stream流处理工具, 包含了工作中绝大部分场景常用的使用方式 import java.math.BigDecimal; import java.util.*; import java.util.function.BiFunction; import java.util.function.Consumer; import java.util.function.Function; import java.util.funct…...

Android 编译和使用libheif

项目中需要使用libheif,libde265,libyuv。一下是相应的cmakelist.txt。这里直接使用了静态库。 里面涉及到c包的链接&#xff0c;需要stdc。 ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/liblibde265.a这个路径由于操作过程中copy出现问题&#xff0c;多了一层路径&…...

新一代零样本无训练目标检测

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月2日21点02分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文链接 点击开启你的论文编程之旅h…...

神经网络入门实战:(九)分类问题 → 神经网络模型搭建模版和训练四步曲

(一) 神经网络模型搭建官方文档 每一层基本都有权重和偏置&#xff0c;可以仔细看官方文档。 pytorch 官网的库&#xff1a;torch.nn — PyTorch 2.5 documentation Containers库&#xff1a;用来搭建神经网络框架&#xff08;包含所有的神经网络的框架&#xff09;&#xff1b…...

写NFC微信小程序跳转Uri标签

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?spma21dvs.23580594.0.0.52de2c1b8bEEGz&ftt&id615391857885 Dim dispstr As String Dim status As Byte Dim status1 As Byte Dim afi As Byte Dim myctrlword As Byte Dim mypiccserial(0 To 7) …...

Gradle vs. Maven: 到底哪个更适合java 项目?

ApiHug ApiHug - API Design & Develop New Paradigm.ApiHug - API Design & Develop New Paradigm.https://apihug.com/ 首先 ApiHug 整个工具链是基于 gradle 构建,包括项目模版&#xff0c; 插件&#xff1b; 说到 Java 项目管理&#xff0c;有两个巨头脱颖而出&a…...

【赛博保安】安全日记之常用术语(一)

"企业的信息安全治理水平&#xff0c;直接取决于安全团队人员的技术专业度&#xff0c;而非运营经验值。所谓的技术&#xff0c;并非指渗透和挖洞的能力&#xff0c;而是指软件开发、IT 架构、网络拓扑相关的知识和经验。 站在乙方的角度来看&#xff0c;技术薄弱的安全人…...

设计模式 更新ing

设计模式 1、六大原则1.1 单一设计原则 SRP1.2 开闭原则1.3 里氏替换原则1.4 迪米特法则1.5 接口隔离原则1.6 依赖倒置原则 2、工厂模式 1、六大原则 1.1 单一设计原则 SRP 一个类应该只有一个变化的原因 比如一个视频软件&#xff0c;区分不同的用户级别 包括访客&#xff0…...

008静态路由-特定主机路由

按照如上配置&#xff0c;用192.168.0.1 电脑ping 192.168.1.1 发现能够ping通 用192.168.0.1 电脑ping 192.168.2.1 发现不能ping通 这是因为192.168.0.1 和 192.168.1.1 使用的是同一个路由器R1。 192.168.0.1 和 192.168.2.1 通信需要先经过R1&#xff0c;再经过R2 &#xf…...

MySQL 慢查询日志记录 SQL优化 性能优化 日志查询 Explain

介绍 慢查询日志记录了所有执行时间超过指定参数(long_query_time&#xff0c;单位:秒&#xff0c;默认10秒)的所有SQL语句的日志。MySQL的慢查询日志默认没有开启&#xff0c;需要在MySQL的配置文件(/etc/my.cnf)中配置针对这些慢查询的SQL语句进行优化。 #开启慢查询开关 s…...

VINS_MONO视觉导航算法【三】ROS基础知识介绍

文章目录 其他文章说明ROSlaunch文件基本概念定义用途 文件结构根标签常用标签\<node>\<param>\<rosparam>\<remap>\<include>\<arg>\<group> 示例基本示例嵌套示例 使用方法启动 *.launch 文件传递参数 总结 ROS topicTopic 的基本…...

Python 3 教程第13篇(集合)

Python3 集合 集合&#xff08;set&#xff09;是一个无序的不重复元素序列。 集合中的元素不会重复&#xff0c;并且可以进行交集、并集、差集等常见的集合操作。 可以使用大括号 { } 创建集合&#xff0c;元素之间用逗号 , 分隔&#xff0c; 或者也可以使用 set() 函数创建集…...

cesium 3dtile ClippingPlanes 多边形挖洞ClippingPlaneCollection

原理就是3dtiles里面的属性clippingPlanes 采用ClippingPlaneCollection&#xff0c;构成多边形来挖洞。 其次就是xyz法向量挖洞 clippingPlanes: new this.ffCesium.Cesium.ClippingPlaneCollection({unionClippingRegions: true, // true 表示多个切割面能合并为一个有效的…...

开发者如何使用GCC提升开发效率GUI操作

看此篇前请先阅读https://blog.csdn.net/qq_20330595/article/details/144139026?spm1001.2014.3001.5502 先上效果图 找到对应的环境版本 配置环境 目录结构 CtrlShiftP c_cpp_properties.json {"configurations": [{"name": "Win32","i…...

什么是隐式类型转换?

隐式类型转换&#xff08;Implicit Type Conversion&#xff09;是指编译器在没有明确要求的情况下&#xff0c;自动地将一种类型的值转换为另一种类型。C 语言支持隐式类型转换&#xff0c;这通常发生在表达式运算或函数调用中&#xff0c;以确保操作数或参数的类型兼容性。 隐…...

爬虫专栏第三篇:Python 实战:运用 requests 突破京东商品评论获取难题(含 cookie 处理与编码设置技巧

简介&#xff1a;本文以京东商品评论为例&#xff0c;详细介绍了使用requests库获取网页数据的过程&#xff0c;包括从打开商品评价页面、抓包分析找到评论接口&#xff0c;到处理cookie参数、解决cookie字符串解析问题&#xff0c;以及设置正确的编码以成功获取评论数据&#…...

HCIE:详解OSPF,从基础到高级特性再到深入研究

目录 前言 一、OSPF协议基本原理 简介 基本原理 OSPF路由器类型 OSPF网络类型 OSPF报文类型和封装 OSPF邻居的建立的维护 DR和BDR的选举 伪节点 LSDB的更新 OSPF的配置 二、OSPF的高级特性 虚连接&#xff08;Virtual-Link&#xff09; OSPF的LSA和路由选择 OSPF…...

第六十六条:谨慎使用本地方法

其实在java中有很多都是采用C或C语言实现的比如native这种的本地方法&#xff0c;感兴趣的可以找源代码看看。 Java Native Interface (JNI) 允许Java应用程序可以调用本地方法&#xff08;native method&#xff09;&#xff0c;所谓本地方法是指使用本地程序设计语言&#xf…...

neo4j如何存储关于liquidity structure的层次和关联结构

在 Neo4j 中存储关于流动性结构&#xff08;liquidity structure&#xff09;的层次和关联结构非常适合&#xff0c;因为 Neo4j 是一个基于图的数据库&#xff0c;能够自然地建模和存储复杂的关系和层次结构。下面是如何在 Neo4j 中设计和实现这样的数据模型的详细步骤和示例。…...

45 基于单片机的信号选择与温度变化

目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机&#xff0c;采用DS18B20检测温度&#xff0c;通过三种LED灯代表不同状态。 采用DAC0832显示信号脉冲&#xff0c;通过8位数码管显示温度。 信号脉冲可以根据两个按键分别调整为正弦…...

2、Three.js初步认识场景Scene、相机Camera、渲染器Renderer三要素

三要素之间关系&#xff1a; 有了虚拟场景Scene&#xff0c;相机录像Camera&#xff0c;在相机小屏幕上看到的Renderer Scene当前空间 Mesh人在场景 Camera相机录像 Renderer显示器上 首先先描述下Scene&#xff1a; 这个场景为三要素之一&#xff0c;一切需要展示的东西都需…...

Java基础面试题06:hashCode()和equals()方法的重要性体现在什么地方?

前言 Java中的hashCode()和equals()方法看似是干同一件事&#xff0c;但它们的使用场景和作用却大有不同。为了让程序更高效、更准确地运行&#xff0c;我们需要对这两者有深入的了解&#xff0c;并掌握它们的重写规则。 hashCode()和equals()的基础知识 什么是hashCode&…...

Matlab Simulink HDL Coder开发流程(一)— 创建HDL兼容的Simulink模型

创建HDL兼容的Simulink模型 一、使用Balnk DUT模板二、从HDL Coder库中选择模块三、为DUT开发算法/功能四、为设计创建Testbench五、仿真验证设计功能六、Simulink模型生成HDL代码 这个例子说明了如何创建一个用于生成HDL代码的Simulink模型。要创建兼容HDL代码生成的MATLAB算法…...

C#基础之方法

文章目录 1 方法1.1 定义方法1.2 参数传递1.2.1 按值传递参数1.2.2 按引用传递参数1.2.3 按输出传递参数1.2.4 可变参数 params1.2.5 具名参数1.2.6 可选参数 1.3 匿名方法1.3.1 Lambda 表达式1.3.1.1 定义1.3.1.2 常用类型1.3.1.3 Lambda 表达式与 LINQ1.3.1.4 Lambda 表达式的…...

Pytest框架学习19--参数化2

1、数据源是yaml 安装yaml&#xff0c;使用safe_load方法读取文件&#xff0c;解析出数据 pip install PyYAML # test_data.yaml test_case_1:a: 2b: 3expected_result: 5test_case_2:a: -1b: 10expected_result: 9test_case_3:a: 0b: 0expected_result: 0# test_code.pyimpor…...

VSCode中“Run Code”运行程序时,终端出现中文乱码解决方法

问题描述 在VSCode中“Run Code”运行程序时&#xff0c;终端输出结果出现中文乱码现象&#xff1a; 解决方法 1. 检查系统cmd的默认编码 查看Windows终端当前编码方式的命令&#xff1a; chcp输出结果是一段数字代码&#xff0c;如936&#xff0c;这说明当前的cmd编码方式…...