C/C++ 用 pthread 进行多线程开发
作为一个程序员,不管你用的开发语言是 C、C++、Java、Python 或者其它,你总会需要处理多任务。
多线程是实现多任务处理的一种最常用的手段,线程相比进程而言显得轻量级。
本文分享如何用 C 进行多线程开发。
核心在于 pthread 这个库。
调用 pthread_create()
函数就可以创建一个线程。
它的函数原型如下:
#include <pthread.h>
extern int pthread_create (pthread_t *__restrict __newthread,
const pthread_attr_t *__restrict __attr,
void *(*__start_routine) (void *),
void *__restrict __arg)
pthread.h 是它的库。
参数说明: 第一个参数是 pthread_t* 也就是代表线程实体的指针 第二个参数为了设置线程的属性,一般为 NULL 第三个参数是线程运行时的函数,这是个函数指针。 第四个参数也是一个指针,它是用来将数据传递进线程的运行函数
下面用一个代码来示例说明。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
//线程函数
void *test(void *ptr)
{
int i;
for(i=0;i<8;i++)
{
printf("the pthread running ,count: %dn",i);
sleep(1);
}
}
int main(void)
{
pthread_t pId;
int i,ret;
//创建子线程,线程id为pId
ret = pthread_create(&pId,NULL,test,NULL);
if(ret != 0)
{
printf("create pthread error!n");
exit(1);
}
for(i=0;i < 5;i++)
{
printf("main thread running ,count : %dn",i);
sleep(1);
}
printf("main thread will exit when pthread is overn");
//等待线程pId的完成
pthread_join(pId,NULL);
printf("main thread exitn");
return 0;
}
创建了名为 test.c 的文件。
这里还有一个重要的函数 pthread_join()
,它的作用是挂起当前的线程,等待指定的线程运行完毕。在示例代码中主线程等待子线程执行完毕后才继续执行后面的代码。
我们现在可以编译然后执行它。
gcc -o test test.c -lpthread
./test
pthread 是一个动态库,编译的时候需要动态链接,不然程序会报错。
运行结果如下:
main thread running ,count : 0
the pthread running ,count: 0
main thread running ,count : 1
the pthread running ,count: 1
main thread running ,count : 2
the pthread running ,count: 2
main thread running ,count : 3
the pthread running ,count: 3
main thread running ,count : 4
the pthread running ,count: 4
main thread will exit when pthread is over
the pthread running ,count: 5
the pthread running ,count: 6
the pthread running ,count: 7
main thread exit
线程与线程之间经常进行数据通讯,前面也提到过,pthread_create()
最后一个参数就是用来传递数据的。
但需要特别注意的是它是 void * 的,也是就是无类型指针,这样做的目的是为了保证线程能够接受任意类型的参数,到时候再强制转换就好了。
我们简单做一些改动。
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
//线程函数
void *test(void *arg)
{
int i;
char* name = (char *)arg;
for(i=0;i<8;i++)
{
printf("the pthread %s running ,count: %dn",name,i);
sleep(1);
}
}
int main (int argc,char* argv)
{
pthread_t pId;
int i,ret;
//创建子线程,线程id为pId
ret = pthread_create(&pId,NULL,test,"sub pthread");
if(ret != 0)
{
printf("create pthread error!n");
exit(1);
}
for(i=0;i < 5;i++)
{
printf("main thread running ,count : %dn",i);
sleep(1);
}
printf("main thread will exit when pthread is overn");
//等待线程pId的完成
pthread_join(pId,NULL);
printf("main thread exitn");
return 0;
}
在线程创建的时候给子线程传递了它的名字,然后在线程的运行函数中进行了强制转换。
我们再看它编译后的运行结果。
main thread running ,count : 0
the pthread sub pthread running ,count: 0
main thread running ,count : 1
the pthread sub pthread running ,count: 1
main thread running ,count : 2
the pthread sub pthread running ,count: 2
main thread running ,count : 3
the pthread sub pthread running ,count: 3
main thread running ,count : 4
the pthread sub pthread running ,count: 4
main thread will exit when pthread is over
the pthread sub pthread running ,count: 5
the pthread sub pthread running ,count: 6
the pthread sub pthread running ,count: 7
main thread exit
运行正常,也达到了目的。
上面是 C 的代码,其实 C++ 也同样适用,只不过需要用 g++ 编译器来编译代码。
本文介绍了简单的 C/C++ 多线程编程方法,初学者认真学习后基本可以用了。
但是,多线程最难的地方其实在于线程之间的数据共享和同步,有空的时候我会专门写一系列的文章来一一说明。
- 浅谈php安全
- 在统一的分析平台上构建复杂的数据管道
- 隐藏在注册表的恶意软件 – Poweliks
- 数千万WordPress和Drupal站点存在DDoS风险
- 利用基因突变和K均值预测地区种群
- 缓冲区溢出攻击初学者手册(更新版)
- 在Python机器学习中如何索引、切片和重塑NumPy数组
- HelloWorld,我的第一趟旅程出发点
- Android OpenGL开发实践 - GLSurfaceView对摄像头数据的再处理
- 走进科学:对七夕“超级病毒”XX神器的逆向分析
- 机器学习 - 朴素贝叶斯分类器的意见和文本挖掘
- 认知指纹:颠覆性的身份认证技术
- 跟我学姿势:极客教你如何科学的看电影
- Discuz 5.x/6.x/7.x投票SQL注入分析
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- JavaScript原型与继承
- 当TKE遇上Coding, 业务如何实现快速迭
- cocos creator 1.x透明渐变效果实现
- Cocos Creator 2.x透明渐变效果实现
- Themeleaf通过ajax局部更新
- ubuntu下利用expect实现screen多窗口开机运行
- hetzner服务器购买和安装debian系统
- 安全通告 | Apache SkyWalking SQL注入漏洞安全风险公告(CVE-2020-13921)
- Cmd Markdown 迁移备份的流程
- PyTorch3:计算图torch.autograph
- spark shell 配置 Kryo 序列化
- Mac里捣腾Kerberos(一)
- Spark on K8S 访问 Kerberized HDFS
- Apache Beam的Docker Demo
- docker login 报错了...