比较线程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,否则会有语法问题。