初探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多线程编程

目录
相关文章
|
17天前
|
存储 Linux API
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
49 17
|
1月前
|
Linux
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
60 26
|
3月前
|
安全 Java API
【JavaEE】多线程编程引入——认识Thread类
Thread类,Thread中的run方法,在编程中怎么调度多线程
|
3月前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
287 2
|
3月前
|
存储 监控 Linux
嵌入式Linux系统编程 — 5.3 times、clock函数获取进程时间
在嵌入式Linux系统编程中,`times`和 `clock`函数是获取进程时间的两个重要工具。`times`函数提供了更详细的进程和子进程时间信息,而 `clock`函数则提供了更简单的处理器时间获取方法。根据具体需求选择合适的函数,可以更有效地进行性能分析和资源管理。通过本文的介绍,希望能帮助您更好地理解和使用这两个函数,提高嵌入式系统编程的效率和效果。
138 13
|
9月前
|
消息中间件 存储 缓存
【嵌入式软件工程师面经】Linux系统编程(线程进程)
【嵌入式软件工程师面经】Linux系统编程(线程进程)
171 1
|
10月前
|
存储 安全 数据管理
Linux系统编程教程之Linux线程函数的使用:讲解Linux线程函数
Linux系统编程教程之Linux线程函数的使用:讲解Linux线程函数
96 1
|
10月前
|
Linux 调度 数据库
Linux下的系统编程——线程同步(十三)
Linux下的系统编程——线程同步(十三)
153 0
Linux下的系统编程——线程同步(十三)
|
10月前
|
NoSQL Unix Linux
Linux下的系统编程——守护进程、线程(十二)
Linux下的系统编程——守护进程、线程(十二)
97 0
Linux下的系统编程——守护进程、线程(十二)