Unix线程API

一:线程标识:pthread_equal 若相等,返回值为0,若不等,返回值非0

#include<pthread.h>
pthread_t pthread_self();
int pthread_equal(pthread_t id1,pthread_t id2);

二:线程创建:

​
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);

​//线程创建成功后,thread保存线程ID
//attr设置线程的属性,默认为NULL,属性后面介绍
//void *(*start_routine) (void *)为线程函数,它的参数为第4个参数void *arg,返回值为void *指针
//pthread_create创建成功的返回值为0,若失败,返回错误编号,注意它并不设置errno的值

三:线程终止

线程终止方式:

1.从线程函数start_route返回;2.线程被同一进程的其它线程取消(调用pthread_cancel); 3.线程自己调用pthread_exit退出。

void pthread_exit(void *ret_val); 

同进程waitpid函数,线程可以使用pthread_join函数等待线程结束

int pthread_join(pthread_t thread, void **ret_val); //调用线程将阻塞,直到指定的线程终止。如果线程是被取消的,ret_val的值会被设为THREAD_CANCEL

特别强调一下,线程函数的返回值,线程函数的返回值是一个void指针,这预示着,返回值可能不止一个值,也有可能是一个复杂结构,另外当线程从线程函数返回后,线程栈内容就已经不存在了,所以试图访问返回线程局部变量指针,总是会出错的,eg:

#include "apue.h"
#include <pthread.h>

struct foo {
	int a, b, c, d;
};

void printfoo(const char *s, const struct foo *fp)
{
	printf("%s", s);
	printf("  structure at 0x%lx\n", (unsigned long)fp);
	printf("  foo.a = %d\n", fp->a);
	printf("  foo.b = %d\n", fp->b);
	printf("  foo.c = %d\n", fp->c);
	printf("  foo.d = %d\n", fp->d);
}

void * thr_fn1(void *arg)
{
	struct foo	foo = {1, 2, 3, 4};

	printfoo("thread 1:\n", &foo);
	pthread_exit((void *)&foo);
}

void * thr_fn2(void *arg)
{
	printf("thread 2: ID is %lu\n", (unsigned long)pthread_self());
	pthread_exit((void *)0);
}

int main(void)
{
	int			err;
	pthread_t	tid1, tid2;
	struct foo	*fp;

	err = pthread_create(&tid1, NULL, thr_fn1, NULL);
	if (err != 0)
		err_exit(err, "can't create thread 1");
	err = pthread_join(tid1, (void *)&fp);
	if (err != 0)
		err_exit(err, "can't join with thread 1");
	sleep(1);
	printf("parent starting second thread\n");
	err = pthread_create(&tid2, NULL, thr_fn2, NULL);
	if (err != 0)
		err_exit(err, "can't create thread 2");
	sleep(1);
	printfoo("parent:\n", fp);
	exit(0);
}

/*程序执行后输出:
[root@localhost threads]# ./a.out
thread 1:
  structure at 0x7f656d781f00
  foo.a = 1
  foo.b = 2
  foo.c = 3
  foo.d = 4
parent starting second thread
thread 2: ID is 140073605015296
parent:
  structure at 0x7f656d781f00
  foo.a = 1836590848
  foo.b = 32613
  foo.c = 1
  foo.d = 0
*/

int pthread_cancel(pthread_t thread); //取消同一进程的其它线程,该函数不会阻塞,它发送取消请求后,立即返回。

注册线程退出时的清理处理程序(类似atexit):

#include <pthread.h>
void pthread_cleanup_push(void (*routine)(void *),void *arg);
void pthread_cleanup_pop(int execute);

其中arg为routine函数的参数,跟atexit不同的是routine只在下列情形下才被调用:

1.线程函数调用,pthread_exit退出后,会调用routine

2.其它线程函数调用pthread_cancel,使得该线程函数退出后,会调用routine

3.在线程函数中自己调用pthread_cleanup_pop,且execute参数非0,会调用routine,若execute参数为0,routine不会调用且被删除。

注意从线程函数return返回,不会调用routine。eg:

#include "apue.h"
#include <pthread.h>

void
cleanup(void *arg)
{
	printf("cleanup: %s\n", (char *)arg);
}

void *
thr_fn1(void *arg)
{
	printf("thread 1 start\n");
	pthread_cleanup_push(cleanup, "thread 1 first handler");
	pthread_cleanup_push(cleanup, "thread 1 second handler");
	printf("thread 1 push complete\n");
	if (arg)
		return((void *)1);
	pthread_cleanup_pop(0);
	pthread_cleanup_pop(0);
	return((void *)1);
}

void *
thr_fn2(void *arg)
{
	printf("thread 2 start\n");
	pthread_cleanup_push(cleanup, "thread 2 first handler");
	pthread_cleanup_push(cleanup, "thread 2 second handler");
	printf("thread 2 push complete\n");
	if (arg)
		pthread_exit((void *)2);
	pthread_cleanup_pop(0);
	pthread_cleanup_pop(0);
	pthread_exit((void *)2);
}

int
main(void)
{
	int			err;
	pthread_t	tid1, tid2;
	void		*tret;

	err = pthread_create(&tid1, NULL, thr_fn1, (void *)1);
	if (err != 0)
		err_exit(err, "can't create thread 1");
	err = pthread_create(&tid2, NULL, thr_fn2, (void *)1);
	if (err != 0)
		err_exit(err, "can't create thread 2");
	err = pthread_join(tid1, &tret);
	if (err != 0)
		err_exit(err, "can't join with thread 1");
	printf("thread 1 exit code %ld\n", (long)tret);
	err = pthread_join(tid2, &tret);
	if (err != 0)
		err_exit(err, "can't join with thread 2");
	printf("thread 2 exit code %ld\n", (long)tret);
	exit(0);
}
/*输出结果
[root@localhost threads]# ./exitstatus
thread 1 returning
thread 1 exit code 1
thread 2 exiting
thread 2 exit code 2
[root@localhost threads]# ./cleanup
thread 1 start
thread 1 push complete
thread 1 exit code 1
thread 2 start
thread 2 push complete
cleanup: thread 2 second handler
cleanup: thread 2 first handler
thread 2 exit code 2
*/

最后一个线程函数:

int pthread_detach(pthread_t thread);

线程结束后,一般会存储线程退出状态信息,其他线程可以调用pthread_join获取该信息(类似waitpid),如若调用pthread_detach,则使得thread标识的线程在结束后,内核自动回收该线程资源,且该线程不能被pthread_join。

 

在全文最后,我们类比一下,进程跟线程的相关API:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值