进击吧,linux(十九) 多线程编程
0赞
线程,被称为轻量级进程,相比多进程,有以下两点不同:
1、 线程和创建他的进程共享代码段、数据段
2、 线程拥有自己独立的栈
同样,对于多线程编程学习,也是基于几个函数的学习。
11.1.1 函数名
pthread_create
11.1.2 函数原形
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *),void *arg)
11.1.3 函数功能
创建新的线程
11.1.4 所属头文件
<pthread.h>
创建线程需要链接pthread库 gcc –lpthread
11.1.5 返回值
成功:0
失败:错误编码
-EAGAIN: 没有资源创建新线程
-EINVAL: 无效的属性设置
-EPERM:没有权限设置属性中的一些参数
11.1.6 参数说明
thread: 线程ID,创建成功的话,*thread会保存创建的线程的ID。
attr: 指定创建线程的属性,如果为NULL,使用默认属性
start_routine: 创建的线程执行的入口函数
arg: 线程入口函数的参数,可以为NULL
11.1.7 示例代码
11.2.1 函数名
pthread_join
11.2.2 函数原形
Int pthread_join(pthread_t thread, void **retval)
11.2.3 函数功能
等待thread的线程结束
11.2.4 所属头文件
<pthread.h>
需要链接pthread库 gcc –lpthread
11.2.5 返回值
成功:0
失败: 错误编码
-EDEADLK: deadlock was detected
-EINVAL: 线程不可等待
-ESRCH: 线程ID不正确
11.2.6 参数说明
thread: 要等待结束的线程ID
retval: 保存线程时退出的状态,一般为NULL,不保存
11.2.7 示例代码
11.3.1 函数名
pthread_exit
11.3.2 函数原形
void pthread_exit(void *retval)
11.3.3 函数功能
结束线程
11.3.4 所属头文件
<pthread.h>
需要链接pthread库 gcc –lpthread
11.3.5 返回值
函数没有返回
11.3.6 参数说明
retval: 保存退出的返回值
11.3.7 示例代码
下面,就编写代码来对上面几个函数进行学习。
代码实现的功能,就是创建3个线程,分别传入三个参数,然后各个线程打印自己的内容。
#include "pthread.h" #include "stdio.h" void *fun_1(void *str) { //将输入的参数强制转化成char *类型 printf("%s\n",(char *)str); sleep(2); pthread_exit(NULL); } void *fun_2(void *a) { //将输入的参数强制转化成int *类型 printf("%d\n",*(int *)a); sleep(3); pthread_exit(NULL); } void *fun_3(void *nul) { printf("welcome to weiqi7777 blog\n"); sleep(4); pthread_exit(NULL); } int main() { pthread_t thread[3]; int arg=5; //创建线程1 pthread_create(&thread[0],NULL,fun_1,(void *)"hello weiqi7777"); //创建线程2 pthread_create(&thread[1],NULL,fun_2,(void *)&arg); //创建线程3 pthread_create(&thread[2],NULL,fun_3,NULL); //等待线程1结束 pthread_join(thread[0],NULL); //等待线程2结束 pthread_join(thread[1],NULL); //等待线程3结束 pthread_join(thread[2],NULL); exit(0); }
这里,要注意的有几个地方。
1、 创建线程的时候,第一个参数是传入线程标识符的地址,所以在这里是&thread[0]
2、 创建线程的最后一个是传入的参数,按照规定的,这个参数的类型是void *,所以在这里对传入的参数进行强制类型转化,防止编译有警告
3、 对于线程的函数,类型是void *(*)(void *)类型的,所以线程的函数要按照这个类型进行定义,不然会报错或者警告
4、 线程执行完毕后,要调用pthread_exit进行线程的退出
5、 主进程中,一定要等待所有线程执行完毕后,才能退出程序,否则当退出程序后,没有执行完毕的线程就直接被退出了。
执行程序,首先是用gcc –lpthread对程序进行编译,然后再执行。发现,执行两次的结果不一样,可以看出,对于多线程,执行的顺序不是固定的。不是谁先创建就先执行哪一个线程。
以上,就是多线程编程的学习了,但是也只是学习了多线程的基本使用,但是问题来了,因为多线程是共享主进程的数据段,那如果多个线程同时对一个数据进行操作的话,又怎么处理了,按照之前学习的,肯定就想到了信号量的互斥,但是在多线程中,是不用这个信号量的,是使用互斥锁。