两种 C++ 多线程编程方式,看完不懂打我...

article/2025/9/16 6:53:01

多线程在实际编程中的重要性不言而喻,对 C++ 而言,当我们需要使用多线程时,有多种方案可供选择。比如 POSIX 线程 pthread、boost::thread 库、C++11 开始支持的 std::thread 库,以及其他一些第三方库 libdispatch(GCD)和 OpenMP 等等。

至于选择哪种多线程编程方案,需要根据你的实际项目、运行平台、团队协作等因素来考虑。一般而言,如果使用的是 Linux 操作系统,那么可以直接使用系统提供的 pthread 库编写多线程 C++ 程序;如果需要跨平台,则推荐使用 C++ 标准的 std::thread 库。

本文将分别介绍 pthreadstd::thread 库的使用。

pthread

基于 POSIX 开发多线程程序需要包含头文件 <pthread.h>

#include <pthread.h>

pthread 提供了一个 pthread_t 类型用来表示一个线程。由于 pthread 库不是 Linux 系统默认的库,因此编译时需要加上 -lpthread 选项以链接 pthread 库。

g++ main.cpp -lpthread

pthread 库提供了一系列 API 用于操作线程,常用的一些接口函数原型如下所示。

// 创建线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg);// 终止线程
void pthread_exit(void *retval);
int pthread_cancel(pthread_t thread);// 线程连接和分离
int pthread_join(pthread_t thread, void **retval);
int pthread_detach(pthread_t thread);

关于这些接口的参数和使用说明,可以参考 Linux 多线程 这篇文章。

下面通过一个示例来演示在 C++ 中如何使用 pthread 接口实现多线程。

#include <iostream>
#include <pthread.h>using namespace std;// 定义线程数量
#define NUM_THREADS 10// 线程函数实体
void *thread_entry(void* args)
{// 对传入的参数进行强制类型转换// 由无类型指针变为整形数指针,然后再读取int tid = *(int *)args;cout << tid << ": Hello thread!" << endl;pthread_exit(NULL);
}int main(void)
{pthread_t tids[NUM_THREADS];int index[NUM_THREADS];// 创建线程for (int i=0; i<NUM_THREADS; i++){index[i] = i;pthread_create(&tids[i], NULL, thread_entry, (void *)&index[i]);}// 等待线程完成for (int i=0; i<NUM_THREADS; i++){pthread_join(tids[i], NULL);}pthread_exit(NULL);return 0;
}

执行下面命令编译程序,注意需要添加 -pthread 选项以链接 pthread 库。

g++ main.cpp -pthread

运行结果:

0: Hello thread!
5: Hello thread!
1: Hello thread!
9: Hello thread!
8: Hello thread!
2: Hello thread!
7: Hello thread!
4: Hello thread!
6: Hello thread!
3: Hello thread!

你看到的顺序和这里的结果可能不一样,不过没关系,这正是多线程运行的效果。

std::thread

C++11 中加入了 <thread> 头文件,此头文件主要声明了 std::thread 线程类。std::thread 类对线程进行了封装,定义了一些表示线程的类、用于互斥访问的类与方法等。

查看 C++ Reference 手册,std::thread 类有以下成员:

其中,成员属性说明如下:

  • std::thread::id 表示线程 ID,定义了在运行时操作系统内唯一能够标识该线程的标识符,同时其值还能指示所标识的线程的状态。
  • native_handle_type 是连接 thread 类和操作系统 SDK API 之间的桥梁,如在 Linux g++(libstdc++)里,native_handle_type 其实就是 pthread 里面的 pthread_t 类型。

成员函数的说明如下:

  • get_id:获取线程 ID,返回一个类型为 std::thread::id 的对象。
  • joinable:检查线程是否可被 join。检查 thread 对象是否标识一个活动(active)的可行性线程。缺省构造的 thread 对象、已经完成 join 的 thread 对象、已经 detach 的 thread 对象都不是 joinable 的。
  • join:调用该函数会阻塞当前线程。阻塞调用者(caller)所在的线程直至被 join 的 std::thread 对象标识的线程执行结束。
  • detach:将当前线程对象所代表的执行实例与该线程对象分离,使得线程的执行可以单独进行。一旦线程执行完毕,它所分配的资源将会被释放。
  • swap:交换两个线程对象所代表的底层句柄。
  • native_handle:该函数返回与 std::thread 具体实现相关的线程句柄。当 thread 类的功能不能满足我们的要求的时候(比如改变某个线程的优先级),可以通过 thread 类实例的 native_handle() 返回值作为参数来调用相关的 pthread 函数达到目的。
  • hardware_concurrency:静态成员函数,返回当前计算机最大的硬件并发线程数目。基本上可以视为处理器的核心数目。

示例:使用 std::thread 创建多个线程并传递参数

#include <iostream>
#include <thread>using namespace std;static const int nt=10;void Hello(int num)
{cout << num << ": Hello thread!" << endl;
}int main(void)
{thread t[nt];// 创建线程for (int i=0; i<nt; i++) {t[i] = thread(Hello, i);}// 等待线程完成for (int i=0; i<nt; i++) {t[i].join();}return 0;
}

可以看到,使用 std::thread 创建线程、传递参数,比使用 pthread 库接口方便多了!

执行 g++ main.cpp -pthread && ./a.out 编译运行以上程序,输出结果如下:

0: Hello thread!
4: Hello thread!
3: Hello thread!
5: Hello thread!
6: Hello thread!
7: Hello thread!
8: Hello thread!
9: Hello thread!
2: Hello thread!
1: Hello thread!

上述例子使用 join() 等待子线程结束,其实我们也可以使用 detach() 不等待子线程。

join() 表示主线程需要等待子线程结束方可执行下一步(串行),而 detach() 则表示让子线程放飞自我,独立于主线程并发执行,主线程后续代码段无需等待。

示例:使用 detach 实现多线程并发

#include <iostream>
#include <thread>using namespace std;static const int nt=10;void Hello(int num)
{cout << num << ": Hello thread!" << endl;
}int main(void)
{thread t[nt];for (int i=0; i<nt; i++) {t[i] = thread(Hello, i);t[i].detach();}cout << "Main thread exit." << endl;return 0;
}

执行 g++ main.cpp -pthread && ./a.out 编译运行以上程序,输出结果如下:

0: Hello thread!
1: Hello thread!
3: Hello thread!
2: Hello thread!
4: Hello thread!
6: Hello thread!
8: Hello thread!
Main thread exit.
9: Hello thread!

可以看到,主线程比子线程先退出了。


点击 GetIoT.tech 学习更多 C++ 编程知识!


http://chatgpt.dhexx.cn/article/jd5mqscg.shtml

相关文章

ARP攻击模拟工具

以下是本人平时的一些小作品&#xff0c;特此和大家一起分享... ARP攻击模拟工具 第一代 说明&#xff1a; 实现模拟以太网的ARP欺骗攻击和IP地址冲突攻击。 此为本人早期作品&#xff0c;固比较简陋和不完善&#xff0c;漏洞及错误之处可能较多请多多包涵&#xff01; 开发环…

ARP断网攻击

在之前的文章当中&#xff0c;我已经向大家介绍了关于ARP的欺骗原理。再进一步&#xff0c;将其中的原理运用到实战中去&#xff0c;又会有什么效果呢&#xff1f;ARP又可以给我们带来哪些具体的作用呢&#xff1f;毕竟实践要来支撑&#xff0c;我们之前学过的ARP欺骗原理。 我…

ARP-欺骗攻击

测试环境&#xff08;kali:192.168.189.7 win7:192.168.189.6 网关:192.168.189.2&#xff09; arpspoof -i eth0 -t 192.168.189.6 192.168.189.2 &#xff08;目标地址网关地址&#xff09; 接收获取的信息 随意登陆一个网站&#xff0c;可发现用户名及密码已被获取。可以…

ARP攻击原理及解决方法,很实用

故障原因】 局域网内有人使用ARP欺骗的木马程序&#xff08;比如&#xff1a;传奇盗号的软件&#xff0c;某些传奇外挂中也被恶意加载了此程序&#xff09;。 【故障原理】 要了解故障原理&#xff0c;我们先来了解一下ARP协议。 在局域网中&#xff0c;通过ARP协议来完成I…

ARP攻击怎么解决最安全

ARP攻击是指攻击者通过伪造网络中的ARP协议数据包&#xff0c;欺骗其他计算机的网络通信&#xff0c;从而实现中间人攻击等目的。 下面是ARP攻击的解决方法&#xff1a; 静态ARP表绑定MAC地址&#xff1a;在网络管理员的控制下&#xff0c;将主机的IP地址与MAC地址进行绑定&am…

ARP攻击及原理

ARP攻击原理:但凡局域网内存在arp攻击&#xff0c;说明网络存在“中间人” 1.PC1需要跟PC2通信&#xff0c;通过ARP请求包询问PC2的MAC地址&#xff0c;由于采用广播的形式&#xff0c;所以交换机会将ARP请求包从接口PC1广播到PC2和PC3。(注&#xff1a;交换机收到广播/组播/未…

ARP攻击、欺骗及防御

一、广播与广播域概述 1、广播与广播域 广播&#xff1a;将广播地址做为目的地址的数据帧。 广播域&#xff1a;网络中能接收到同一个广播所有节点的集合。 2、MAC地址广播 广播地址为FF-FF-FF-FF-FF-FF 3、IP地址广播 1&#xff09;255.255.255.255 2&#xff09;广播…

ARP攻击原理和kali实现ARP攻击

目录 一、ARP协议和ARP攻击1.ARP协议2.利用Wireshark分析ARP数据包3.ARP攻击 二、kali实现ARP攻击和ARP欺骗1.实验过程2.问题记录T_T 一、ARP协议和ARP攻击 1.ARP协议 ARP协议&#xff0c;地址解析协议&#xff08;Address Resolution Protocol&#xff09;&#xff0c;用来实…

怎么处理ARP攻击

ARP故障说明: ping 的时候可能好久才能接收到一个响应&#xff0c;或者说干脆就Ping不通。网络时好时坏&#xff0c;通过ARP -a命令不能看到同网段的在线用户&#xff0c;但是net view 可以看到全网开放共享的电脑名&#xff0c;这时候就需要注意了&#xff0c;可能是ARP攻击。…

网络安全--ARP攻击原理与防护

目录 一.ARP的原理 二.ARP攻击现象及危害 三.ARP攻击的原理 四.ARP防护 在局域网当中&#xff0c;有一个协议由于它的特性一旦遭受攻击就非常麻烦。首先是它的攻击门槛比较低&#xff0c;找到一些小工具就能实现攻击&#xff0c;而且危害极大。这个协议就是ARP协议。 ARP攻击是…

渗透技术——ARP攻击

Part 1: ARP攻击介绍 ARP&#xff08;Address Resolution Protocol&#xff0c;地址解析协议&#xff09;是一个位于TCP/IP协议栈中的底层协议&#xff0c;负责将某个IP地址解析成对应的MAC地址。而ARP攻击就是通过伪造IP地址和MAC地址实现ARP欺骗&#xff0c;能够在网络中产生…

Linux操作系统及其发行版本

文章目录 Linux是什么Liunx与WindowsLinux的发行版本1. Debian系列&#xff1a;2. Slackware系列&#xff1a;3. Redhat系列&#xff1a;4. 其他发行版本&#xff1a; Linux是什么 Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基于POSIX和UNIX的多用户、…

linux查看系统版本命令

*一、查看Linux系统发行版本 * 命令1&#xff1a;lsb_release -a 该命令适用于所有Linux系统&#xff0c;会显示出完整的版本信息&#xff0c;包括Linux系统的名称&#xff0c;如Debian、Ubuntu、CentOS等&#xff0c;和对应的版本号&#xff0c;以及该版本的代号&#xff0c…

哪些是linux系统版本,linux系统主要有哪些版本

linux系统主要版本有&#xff1a;Redhat版本&#xff0c;基于RPM包的YUM包管理方式&#xff1b;2.CentOS版本&#xff0c;免费的、开源的、可以重新分发的linux发行版&#xff1b;3.Ubuntu版本&#xff0c;拥有漂亮的用户界面的系统&#xff1b;4.Mandriva版本&#xff0c;KDE桌…

Linux操作系统介绍及版本

1.1 认识Linux Linux操作系统是基于UNIX以网络为核心的设计思想&#xff0c;是一个性能稳定的多用户网络操作系统&#xff0c;Linux能运行各种工具软件、应用程序以及网络协议&#xff0c;它支持安装在32位和64位CPU硬件上。 通常来讲&#xff0c;Linux这个词只表示Linux内核&a…

Linux版本简介

Linux系统最早由LinusTorvalds在1991年开始编写&#xff0c;在此诞生之前同时也具备了五大前提条件&#xff1a;UNIX操作系统、MINIX 操作系统、GNU计划、POSIX标准、INTERNET。先让我们看一下Linux系统的发行版本&#xff0c;包括Redhat、Ubuntu、Fedora、SUSE、Slackware、De…

Linux各个系统版本及区别(Ubuntu,CentOS..)

一、概览 Linux的版本号分为两部分&#xff1a;内核版本和发行版本。 内核版本&#xff1a;不包含外围程序GNU程序库和工具&#xff0c;命令行shell&#xff0c;图形界面的X Window系统和相应的桌面环境等 发行版本&#xff1a;RedHatLinux&#xff0c;CentOS, Ubuntu&#xff…

网站整合CKEditor和CKFinder(Java版)

准备文件 CKEditor: 在 http://ckeditor.com/download &#xff0c;可以下载到各种版本的CKEditor&#xff0c;包括完整版full、标准版standard、基础版basic等。同时也可定制的下载&#xff0c;可以选择Toolbar类型、插件、语言等。 CKEditor for java: 在http://ckeditor.c…

编辑组件CKEditor与文件管理组件CKFinder

ckeditor ckfinder ckeditor:html文本编辑插件&#xff0c;源码为javascript编写,实现对文本域的托管 下载时选择Full Package版本 解压后,去除一些不必要的文档;放置到js目录下即可 当然,也可以看看搭建案例samples 在这里可以设置需要的组件功能按钮 勾选完成后;得到配置代…

(ckeditor+ckfinder用法)Jquery,js获取ckeditor值 .

2010-10-15 17:14 1244人阅读 评论(1) 收藏 举报 CKEditor 3.3.1 和 ckfinder 2.0 配置 with jQuery 1.42 请看33楼&#xff01; CKEditor 3.2 在 asp.net 下进行配置的方法&#xff1a; 官方网站&#xff1a;CKEditor CKFinder 1、CKEditor 不具备上传功能&#xff0…