说明:只供学习交流,转载请注明出处
一,创建线程和退出线程
在Linux系统中,所有与线程相关的函数都是以pthread开头的。pthread_create函数用于在当前进程中加入新的线程。Linux系统中线程的创建与UNIX系统存在着不同。在Linux系统中,当调用pthread_create函数来创建线程时,系统首先先创建一个新的进程,再在该进程内再创建需要的线程。新创建的进程与原有的进程是共享内存的,因此,与调用fork而产生的进程存在着本质的区别。同时,在第一次调用pthread_create函数时,系统还会创建一个管理进程,用于对多线程的管理。
头文件 |
#include <pthread.h> |
||
函数原型 |
int pthread_create(pthread_t * tidp, const pthread_attr_t *attr, void *(*start_rtn)(void), void *arg) |
||
返回值 |
成功 |
失败 |
是否设置errno |
0 |
-1 |
是 |
函数功能:创建新的线程
参数说明:tidp:线程id attr:线程属性(通常为空) start_rtn:线程要执行的函数
arg:start_rtn的参数
说明:新的线程将拥有自己的堆。同时,从创建线程处继承调度优先级。如果pthread_create函数调用失败,将不会创建新的线程。
错误信息:
EAGAIN:系统没有足够的资源来创建新的线程,或系统达到最大线程数(PTHREAD_THREADS_MAX)。
EINVAL:参数attr非法。
EPERM:函数调用者没有相应的设置线程调度参数或策略的权限。
注意:因为pthread的库不是linux系统的库,所以在进行编译的时候要加上-lpthread
# gcc filename –lpthread
实例:
程序为使用pthread_create函数来创建线程的实例。在程序中调用pthread_create函数来启动新的线程。调用sleep函数的目的是保证进程在新线程运行之前不会退出。具体代码如下:
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
void *thread_info(void)
{
printf("In thread_info function!\n");
return NULL;
}
int main(void)
{
pthread_t thread_id;
int ret;
//创建线程
ret = pthread_create(&thread_id, NULL, (void*)thread_info, NULL);
if (ret == -1)
{
perror("Cannot create new thread!");
return (1);
}
//保证主线程会在创建线程执行完成之后结束
sleep(5);
return (0);
}
运行结果:
[root@localhost test]# gcc -Wall -lpthread pthread_create.c -o pthread_create
[root@localhost test]# ./pthread_create
In thread_info function!
[root@localhost test]#
补充:
函数pthread_tpthread_self(void)
功能:获取调用线程的threadidentifier(线程ID)。
二,pthread_exit函数
如果进程中任何一个线程中调用exit或_exit,那么整个进程都会终止。线程的正常退出方式有以下几种:
(1):创建线程时指定要执行的函数执行完毕。
(2):创建线程的进程退出。
(3):某个线程调用了exec函数。
(4):线程调用了pthrea_exit函数退出。
(5):线程被pthread_cancel终止。
从上面可以了解到使用pthread_exit函数可以让运行的进程退出。pthread_exit函数的具体信息如下所示:
pthread_exit函数
头文件 |
#include <pthread.h> |
||
函数原型 |
void pthread_exit(void *value_ptr); |
||
返回值 |
成功 |
失败 |
是否设置errno |
—— |
—— |
—— |
说明:pthread_exit函数用于结束线程的运行。参数value_ptr设置线程退出的返回值。由于value_ptr为指向内存空间的指针,value_ptr必须指向线程退出后任然存在的空间,value_ptr指针不能执行局部变量。
如果在进程的main函数中调用pthread_exit函数,主函数所在的线程将退出。但是使用return的话,实际上进程将退出,从而导致所有的线程退出。如果return包含在pthread_cleanup_push函数和pthread_cleanup_pop函数之间,那么线程将不会调用清理函数,程序将提示出现段错误。
三,线程等待
创建一个线程,在进程中通过调用函数pthread_join等待线程结束,这个函数是一个线程阻塞的函数,调用它的进程将一直等待直到被等待的线程结束为止,当函数返回时,被等待线程的资源被回收。具体函数如下:
pthread_join函数
头文件 |
#include <pthread.h> |
||
函数原型 |
int pthread_join(pthread_t thread, void **value_ptr); |
||
返回值 |
成功 |
失败 |
是否设置errno |
0 |
非0值 |
是 |
函数功能:等待一个线程结束
参数说明:thread为要等待的线程标识符;value_ptr为一个用户自定义的指针,它可以用来存储被等待进程的返回值。
错误信息:
EINVAL:参数thread中指定的线程为非可连接的线程。
ESRCH:无thread参数指定的线程。
EDEADLK:指定线程中存在死锁。
实例:
#include <stdio.h>
#include <pthread.h>
//用于保存线程中要显示的信息的结构体
struct thread_param
{
char info;
int num;
};
//线程要执行的函数
void *thread_fun(void *param)
{
struct thread_param *p;
p = (struct thread_param*)param;
int i;
for (i = 0; i < p->num; i++)
{
printf("%i: %c\n", i, p->info);
}
return (NULL);
}
int main(void)
{
pthread_t tid1, tid2;
struct thread_param info1;
struct thread_param info2;
int ret;
info1.info = 'T';
info1.num = 2;
//创建线程,线程要执行的函数参数为info1
ret = pthread_create(&tid1, NULL, thread_fun, (void *)&info1);
if (ret == -1)
{
perror("Cannot create new pthread");
return (1);
}
info2.info = 'S';
info2.num = 3;
//创建线程,线程要执行的函数参数为info2
ret = pthread_create(&tid2, NULL, thread_fun, (void *)&info2);
if (ret == -1)
{
perror("Cannot create new pthread");
return (1);
}
//等待创建的线程tid1的结束
if (pthread_join(tid1, NULL) != 0)
{
perror("Call pthread_join function fail");
return (1);
}
//等待创建的线程tid2的结束
if (pthread_join(tid2, NULL) != 0)
{
perror("Call pthread_join function fail");
return (1);
}
return (0);
}
运行结果:
[root@localhost test]# ./pthread_join
0: T
1: T
0: S
1: S
2: S
[root@localhost test]#