现在的位置: 首页 > 综合 > 正文

多线程程序设计1

2013年02月01日 ⁄ 综合 ⁄ 共 3319字 ⁄ 字号 评论关闭

 

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

 

一,创建线程和退出线程

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]# 

 

 

 

 

 

 

 

 

抱歉!评论已关闭.