pthread_equal(),比较线程ID
NAME
pthread_equal - compare thread IDs 比较两个线程ID
SYNOPSIS
#include <pthread.h>
int pthread_equal(pthread_t t1, pthread_t t2);
// 不清楚 线程ID 类型,不能直接按照int类型数值的比较方法。
用-pthread编译并链接。
如果两个线程id相等,则pthread_equal()返回一个非零值;否则,返回0。
pthread_self(), 获取当前线程的线程ID
NAME
pthread_self - obtain ID of the calling thread
SYNOPSIS
#include <pthread.h>
pthread_t pthread_self(void);
Compile and link with -pthread.
RETURN VALUE
This function always succeeds, returning the calling thread's ID.
pthread_create() 线程的创建
NAME
pthread_create - create a new thread
SYNOPSIS
#include <pthread.h>
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.
RETURN VALUE
On success, pthread_create() returns 0; on error, it returns an error number, and the contents of *thread are undefined.
线程的调度取决于调度器的调度策略
由于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() 正常结束一个线程
线程的终止 的三种方式:
1 线程从启动例程返回,返回值就是线程的退出码
2 线程可以被同一进程中的其他线程取消
3 线程调动 pthread_exit()函数
NAME
pthread_exit - terminate calling thread 正常结束一个线程
SYNOPSIS
#include <pthread.h>
void pthread_exit(void *retval);
Compile and link with -pthread.
RETURN VALUE
This function does not return to the caller.
与return 不同,调用 pthread_exit()结束线程 会实现线程栈的清理。
pthread_join():线程收尸
相当于 进程阶段的wait()操作,作用是 线程收尸,等一直等待线程运行结束 再收尸
和wait() 不同的时候 可以指定 收尸目标,wait()只有收到了 才知道收到的是谁。
NAME
pthread_join - join with a terminated thread
SYNOPSIS
#include <pthread.h>
int pthread_join(pthread_t thread, void **retval);
//thread 指定收尸的目标线程
// void **retval 为空,表示 只收尸,不关心状态
Compile and link with -pthread.
RETURN VALUE
On success, pthread_join() returns 0; on error, it returns an error number.
#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()钩子函数,这里 我们可以自己决定 执行哪个挂载钩子上面的函数,执行起来同样也是逆序。
NAME
pthread_cleanup_push, pthread_cleanup_pop - push and pop thread cancellation clean-up handlers
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,否则会有语法问题。