多线程程序设计1

来源:互联网 发布:国内域名资源分布状况 编辑:程序博客网 时间:2024/04/27 21:31

 

说明:只供学习交流,转载请注明出处

 

一,创建线程和退出线程

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:线程要执行的函数     argstart_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;//创建线程,线程要执行的函数参数为info1ret = pthread_create(&tid1, NULL, thread_fun, (void *)&info1);if (ret == -1){perror("Cannot create new pthread");return (1);}info2.info = 'S';info2.num = 3;//创建线程,线程要执行的函数参数为info2ret = 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: T1: T0: S1: S2: S[root@localhost test]# 


 

 

 

 

 

 

 

 

原创粉丝点击