初探linux pthread多线程编程

简介:

多线程的创建,pthread_create:

1 //头文件
2   #include<pthread.h>
3 //函数声明
4   intpthread_create(/*指向线程标识符的指针*/,/*线程属性参数,通常为NULL*/,/*返回值是void类型指针的函数 */,/*运行函数的参数*/);
5 //成功返回0,失败返回错误编号。

注意:被创建的线程可能在pthread_create执行完毕之前就开始执行。

编译注意:编译时注意加上-lpthread参数,以调用静态链接库。因为pthread并非Linux系统的默认库

等待线程结束,pthread_join:

1 pthread_join(/*等待的线程标识符*/,/*传入指针,用于存储被等待线程的返回值,通常为NULL*/);

一开始以为这个函数没啥用,所以第一次写多线程没加入这个函数,结果发现用线程执行的函数没执行程序就结束了。才明白这个函数是让主线程阻塞在这个地方等待子线程结束。

如果主线程执行完,return 0,子线程都会直接结束掉,因为系统直接回收资源了。

一个简单的栗子:

01 #include<iostream>
02 #include<cstdio>
03 #include<string>
04  
05 #include<fcntl.h>
06 #include<errno.h>      //错误代码
07 #include<stdlib.h>  //exit函数
08 #include <pthread.h>   //线程库
09  
10 using namespace std;
11  
12 pthread_cond_t cond;
13 pthread_mutex_t mutex;
14 int count=0;
15 void *play(void *arg)                    //注意这个函数,返回值和参数都是void指针。
16 {
17     cout<<"child thread"<<endl;
18 }
19 int main()
20 {
21    pthread_t pid;
22     cout<<"main thread"<<endl;
23    pthread_create(&pid,NULL,play,NULL);       //创建线程
24    pthread_join(pid,NULL);                   //等待线程结束
25    return 0;
26 }

至此,简单的多线程可以写了。

 运行函数的参数传递问题:

就是pthread_create的最后一个参数。这是给运行的函数传递参数用的。

没有参数:

多好,直接给个NULL就完了。

一个参数:

可以在样例代码中看到,传入的函数的参数是一个void指针,所以pthread_create的第四个参数接受的也是一个void指针。对变量取个地址即可传入,然后在函数中重新转换回原本变量的指针类型,再解引用即可。(这里需要注意的是传入地址,线程中对变量的改变会引起原变量的改变,如果指针指向一块动态内存,一旦内存被回收,也会出现问题

多个参数:

毕竟,一个函数传入多个参数是很常见的。但是运行函数的参数只有一个void指针,所以要传入多个参数就必须想办法把它们“打包”通过那个void指针传递进去。

于是,第一种方法就是采用一个结构体,对多个变量打包传入。像单个参数一样指针转换一下,提取出变量即可。

第二种方法,使用void数组。创建一个void*[],里面保存指向你的所有参数的指针,然后把这个void*[]传递给pthread_create。

01 void*   route(void*   args)  
02 {  
03                   int*   iptr   =   ((void**)args)[0];             //注意这里,是void**,而不是void*
04                   float*   fptr   =   ((void**)args)[1];  
05                   char*   str   =   ((void**)args)[2];  
06                   printf("integer:   %d/nfloat:   %f/nstring:   %s/n",   *iptr,   *fptr,   str);  
07                   return   0;  
08 }  
09      
10 int   main(void)  
11 {  
12                   pthread_t   thr_id;  
13                   int   ival   =   1;  
14                   float   fval   =   10.0F;  
15                   char   buf[]   =   "func";  
16                   void*   arg[3]={&ival,   &fval,   buf};          //void指针数组
17                   pthread_create(&thr_id,   NULL,   route,   arg);  
18                   sleep(1);  
19 }

和第一种方法的不同之处在于args是一个void指针,但是我们要把它当作二级指针用void指针是可以指向任何地址的,args其实是指向那个arg[]数组的,我们知道数组其实就是一个指针,所以args指针的指针

但是void指针是不能解引用的,它不代表真实的变量,因为真实的变量还有变量大小,对应的指针能根据变量大小来加减,void*是没有的,也就不能做算法操作

所以代码中为了支持下标操作,把void*转换成void**

不是说了void*是没有类型的么,为啥void**能支持下标操作?

void*  是说: 这是一个指针,它指向的对象未知.
void*  是说: 这是一个指针,它指向一个void* 型的数据结构.void*是一个指针指针长度是已知的,所以也就可以支持下标操作了。

总结:

总算是能写个多线程的程序了,但是这个离会多线程还差得远,因为多线程的难度并不在于创建线程,而是在于线程的同步。

在linux中线程其实并没有专门独立开来说,实际上线程是使用轻量级进程实现的。所以linux是每个进程只有一个线程。

pthread_create和fork的区别:

fork出来的新进程和父进程是处于一种copy。是一个新的副本。但是pthread_create创建的线程却共享变量

转载请注明:旅途@KryptosX » 初探linux pthread多线程编程

目录
相关文章
|
1月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
146 6
|
4月前
|
Java API 微服务
为什么虚拟线程将改变Java并发编程?
为什么虚拟线程将改变Java并发编程?
306 83
|
1月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
239 0
|
2月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
224 16
|
6月前
|
机器学习/深度学习 消息中间件 存储
【高薪程序员必看】万字长文拆解Java并发编程!(9-2):并发工具-线程池
🌟 ​大家好,我是摘星!​ 🌟今天为大家带来的是并发编程中的强力并发工具-线程池,废话不多说让我们直接开始。
253 0
|
9月前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
7月前
|
并行计算 Linux
Linux内核中的线程和进程实现详解
了解进程和线程如何工作,可以帮助我们更好地编写程序,充分利用多核CPU,实现并行计算,提高系统的响应速度和计算效能。记住,适当平衡进程和线程的使用,既要拥有独立空间的'兄弟',也需要在'家庭'中分享和并行的成员。对于这个世界,现在,你应该有一个全新的认识。
285 67
|
6月前
|
安全 算法 Ubuntu
Linux(openssl)环境:编程控制让证书自签的技巧。
总结:在Linux环境中,OpenSSL是一个非常实用的工具,可以帮助我们轻松地生成自签名证书。通过上述三个简单步骤,即可为内部网络、测试环境或开发环境创建自签名证书。但在公共访问场景下,建议购买经过权威认证机构签发的证书,以避免安全警告。
307 13
|
6月前
|
Linux 程序员 API
CentOS如何使用Pthread线程库
这就是在CentOS下使用Pthread线程库的全过程。可见,即使是复杂的并发编程,只要掌握了基本的知识与工具,就能够游刃有余。让我们积极拥抱并发编程的魅力,编写出高效且健壮的代码吧!
177 11
|
8月前
|
JavaScript Ubuntu Linux
如何在阿里云的linux上搭建Node.js编程环境?
本指南介绍如何在阿里云Linux服务器(Ubuntu/CentOS)上搭建Node.js环境,包含两种安装方式:包管理器快速安装和NVM多版本管理。同时覆盖全局npm工具配置、应用部署示例(如Express服务)、PM2持久化运行、阿里云安全组设置及外部访问验证等步骤,助你完成开发与生产环境的搭建。