C pthread函数
线程创建
1
2
3
4
int pthread_create(pthread_t * restrict tidp,
const pthread_attr_t * restrict attr,
void *(* start_rm)(void *),
void *restrict arg);
获取线程标识符
1
pthread_t pthread_self(void);
例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
#include <stdio.h> #include <pthread.h> void * run (void *args) { printf("pthread id = %d\n", pthread_self()); return NULL; } int main() { int ret; pthread_t tid; ret = pthread_create(&tid, NULL, run, NULL); if (ret) { printf("pthread create error\n"); return 1; } void *val; pthread_join(tid, &val); return 0; }
线程退出
1
void pthread_exit(void * rval_ptr);
rval_ptr
是线程结束时的返回值,可以由 pthread_join()
获取
线程退出方式: 1. 线程从线程函数中返回 2. 线程被另一个线程终止 3. 线程自己调用 pthread_exit()
函数
线程等待
1
int pthread_join(pthread_t tid, void ** rval_ptr);
调用后,一直等待指定的线程结束才返回函数,被等待线程的资源会被收回
例2:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
void * run2 ( void *args) { int i = 0; while (i < 10) { i++; printf("pthread id = %d\n", pthread_self()); if (i == 5) { pthread_exit((void *)i); // 也可以使用return来返回 // return (void *)i; } } return NULL; } int main() { int ret; pthread_t tid; ret = pthread_create(&tid, NULL, run2, NULL); if (ret) { printf("pthread create error\n"); return 1; } void *val; pthread_join(tid, &val); printf("val = %d\n", val); return 0; }
线程清除
- 正常退出 : 通过
pthread_exit()
或return
的方式返回 非正常退出 : 其他线程的干预下或自身运行错误而退出
1
void pthread_cleanup_push(void (* rtn)(void *), void * arg);
函数说明:将清除函数压入清除栈。
rtn
是清除函数,arg
是清除函数的参数1
void pthread_cleanup_pop(int execute);
函数说明:将清除函数弹出清除栈。执行到
pthread_cleanup_pop()
时,参数execute
决定是否在弹出清除函数的同时执行该函数,非0时执行1
int pthread_cancel(pthread_t thread);
函数说明:取消线程,该函数在其他线程中调用,用来强行杀死指定的线程
在
pthread_cleanup_push
和pthread_cleanup_pop
之间程序段中的终止动作(包括正常退出和异常退出,不包括return),都将执行pthread_cleanup_push
所指定的清理函数例3:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
void *clean (void *arg) { printf("cleanup: %s\n", (char *)arg); return (void *)0; } void *thr_fn1 (void *arg) { printf("thread 1 start\n"); pthread_cleanup_push((void *)clean, "thread 1 first handler"); pthread_cleanup_push((void *)clean, "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((void *)clean, "thread 2 first handler"); pthread_cleanup_push((void *)clean, "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() { int err; pthread_t tid1, tid2; void *tret; err = pthread_create(&tid1, NULL, thr_fn1, (void *)1); if (err != 0) { printf("main1:error...\n"); return -1; } err = pthread_create(&tid2, NULL, thr_fn2, (void *)1); if (err != 0) { printf("main2:error...\n"); return -1; } err = pthread_join(tid1, &tret); if (err != 0) { printf("main3:error...\n"); return -1; } printf("thread 1 exit code %d\n", (int)tret); err = pthread_join(tid2, &tret); if (err != 0) { printf("main4:error...\n"); return -1; } printf("thread 2 exit code %d\n", (int)tret); return 0; }
pthread_exit()用于线程退出,可以指定返回值,以便其他线程通过pthread_join()函数获取该线程的返回值。return,是函数返回,不一定是线程函数哦! 只有线程函数中return,线程才会退出;
pthread_exit()、return都可以用pthread_join()来接收返回值的,也就是说,对于pthread_join()函数来说是没有区别的;
pthread_cleanup_push()所指定的清理函数支持调用pthread_exit()退出线程和异常终止,不支持return;
pthread_exit()为直接杀死/退出当前进程,return则为退出当前函数,但是在g++编译器中,main中的return会被自动优化成exit(),所以在主函数中使用return会退出该进程所有线程的运行;
return会调用局部对象的析构函数,而pthread_exit()不会(线程本来就不建议用pthread_exit()这类方法自杀的,正确的方法是释放所申请的内存后return)。