十一_线程2-线程标识的获取,比较,线程的创建,结束,收尸,线程栈清理

比较线程ID

在这里插入图片描述

pthread_self(), 获取当前线程的线程ID
在这里插入图片描述

pthread_create() 线程的创建

在这里插入图片描述
线程的调度取决于调度器的调度策略
由于pthread库不是标准linux库,所以编译 改为gcc thread.c -lpthread 即可。

实验1

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

static void* func(void* p)
{
	puts("Thread is working!");
	return NULL;
}

int main()
{
	pthread_t tid;
	int err;

	puts("Begin!");

	err = pthread_create(&tid,NULL,func,NULL);	
	if(err)
	{
		fprintf(stderr,"pthread_crearte():%s\n",strerror(err));
		exit(1);
	}

	puts("End!");
	exit(0);

}

mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ gcc pthread_create1.c  -lpthread
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ ./a.out 
Begin!
End!
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 

线程的调度取决于调度器策略,在我们创建的线程还没来得及 调度的时候,当前进程就exit(0)结束了。

pthread_exit() 正常结束一个线程

在这里插入图片描述

pthread_join():线程收尸
相当于 进程阶段的wait()操作,作用是 线程收尸,等一直等待线程运行结束 再收尸
和wait() 不同的时候 可以指定 收尸目标,wait()只有收到了 才知道收到的是谁。
在这里插入图片描述

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

static void* func(void* p)
{
	puts("Thread is working!");	
	pthread_exit(NULL);
	//return NULL;
}

int main()
{
	pthread_t tid;
	int err;

	puts("Begin!");

	err = pthread_create(&tid,NULL,func,NULL);	
	if(err)
	{
		fprintf(stderr,"pthread_crearte():%s\n",strerror(err));
		exit(1);
	}

	pthread_join(tid,NULL);//线程收尸,一直等待线程结束后收尸
	puts("End!");
	exit(0);

}



mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ gcc pthread_create1.c -lpthread
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ ./a.out 
Begin!
Thread is working!
End!
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 

可以看到 调度线程是等待 tid线程调度结束后 才结束进程,就是因为 pthread_join() 线程收尸函数, 一直在等待目标线程结束,后收尸。执行完收尸动作,进程才会exit(0) 结束进程。

栈的清理
pthread_cleanup_push()
pthread_cleanup_pop()

回顾:钩子函数 atexit(),在进程正常终止的时候,该函数将会被调用,并逆序调用挂在钩子上面的函数,这里的逆序调用挂载钩子上面的函数这个操作,我们无法介入,一定会被执行。

pthread_cleanup_push() 函数 类似于 atexit(),挂载钩子函数,而 pthread_cleanup_pop() 用于取下挂在钩子上面的函数,执不执行看参数,相比于 atexit()钩子函数,这里 我们可以自己决定 执行哪个挂载钩子上面的函数,执行起来同样也是逆序。

SYNOPSIS
       #include <pthread.h>

// 将函数挂在钩子上。挂载的函数,挂载的函数的参数
       void pthread_cleanup_push(void (*routine)(void *),
                                 void *arg);

//决定当前从钩子上面取下来的函数是否被调用。  参数决定是否调用
       void pthread_cleanup_pop(int execute);

       Compile and link with -pthread.

需要注意的是
pthread_cleanup_push()
pthread_cleanup_pop()
这两个函数是 宏,两个宏是组合使用,必须成对出现,否则会有语法错误。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>

static void cleanup_func(void* p)
{
	puts(p);
}

static void* func(void* p)
{
	puts("Thread is working!");	


	pthread_cleanup_push(cleanup_func,"cleanup1");
	pthread_cleanup_push(cleanup_func,"cleanup2");
	pthread_cleanup_push(cleanup_func,"cleanup3");

	puts("push over!");
	
	pthread_cleanup_pop(1);
	pthread_cleanup_pop(1);
	pthread_cleanup_pop(1);
	
	pthread_exit(NULL);
	//return NULL;
}

int main()
{
	pthread_t tid;
	int err;

	puts("Begin!");

	err = pthread_create(&tid,NULL,func,NULL);	
	if(err)
	{
		fprintf(stderr,"pthread_crearte():%s\n",strerror(err));
		exit(1);
	}

	pthread_join(tid,NULL);
	puts("End!");
	exit(0);

}


mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ gcc pthread_create1.c -lpthread
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ ./a.out 
Begin!
Thread is working!
push over!
cleanup3
cleanup2
cleanup1
End!
mhr@ubuntu:~/Desktop/xitongbiancheng/parallel/thread/posix$ 

如果是pthread_cleanup_pop(0); 则不执行,即只弹栈,而不执行对应函数。就算只弹栈,不执行,也一定要写上,有几个push,就一定要有对应的几个 pop,否则会有语法问题。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux老A

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值