一、pthread_self函数
功能:获取线程ID。
pthread_t pthread_self(void);
- 线程ID:pthread_t类型,本质:在Linux为无符号整数(%lu),其他系统可能是结构体实现
- 线程ID是进程内部识别标志。(两个进程间,线程ID允许相同)
注意:不应使用全局变量pthread_t tid,在子线程通过pthread_create传出参数来获取线程ID,而应使用pthread_self.
二、pthread_create函数
功能:创建一个新线程
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
typedef void *(*start_routine) (void *);
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, start_routine th_fn, void *arg);
参数:
- pthread_t:当前Linux可理解为:typedef unsigned long int pthread_t;
- 参数1:传出参数,保存系统为我们分配好的线程ID
- 参数2:通常传NULL,表示使用线程默认属性。若想使用具体属性也可以修改该参数。
- 参数3:函数指针,指向线程主函数(线程体),该函数运行结束,则线程结束。
- 参数4:线程执行期间所使用的参数。
1. 测试代码:
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>void *thrd_func(void *arg)
{printf("In thread:thread id = %lu, pid = %u\n", pthread_self(), getpid());return NULL;
}int main(void)
{pthread_t tid;int ret; printf("In main 1: thread id = %lu, pid = %u\n", pthread_self(), getpid());ret = pthread_create(&tid, NULL, thrd_func, NULL);if(ret != 0) {fprintf(stderr, "pthread_create error: %s\n", sterror(ret));exit(1);}sleep(1); printf("In main 2: thread id = %lu, pid =%u\n", pthread_self(), getpid()); return 0;
}
输出结果:
2. 测试代码:
#include<stdio.h>
#include<pthread.h>
#include<unistd.h>
#include<stdlib.h>
#include<string.h>void *thrd_func(void *arg)
{int i = (int) arg;sleep(i);printf("%dth thread: id = %lu, pid = %u\n", i+1, pthread_self(), getpid());return NULL;
}int main(void)
{pthread_t tid;int ret, i; for(i = 0; i < 5; i++) {ret = pthread_create(&tid, NULL, thrd_func, (void *)i);if(ret != 0) {fprintf(stderr, "pthread_create%s\n", strerror(ret));exit(1);}}sleep(i);return 0; //将当前进程退出
}
输出结果:
三、线程与共享
注意:线程间共享全局变量!
【牢记】线程默认共享数据段、代码段等地址空间,常用的是全局变量,而进程间不共享变量,只能借助mmap。
线程共享资源:
- 文件描述符
- 每种信号的处理方式
- 当前工作目录
- 用户ID和组ID
- 内存地址空间(.text/ .data/ .bss/heap/共享库)
线程非共享资源
- 线程ID
- 处理器现场和栈指针(内核栈)
- errno变量
- 信号屏蔽字
测试代码:
#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>int var = 100;void *tfn(void *arg)
{var = 200;printf("thred\n");return NULL;
}int main(void)
{printf("At first var = %d\n", var);pthread_t tid;pthread_create(&tid, NULL, tfn, NULL);sleep(1);printf("after pthread_create, var = %d\n", var);return 0;}
输出结果:
四、pthread_exit函数
功能:将单个线程退出
void pthread_exit(void *retval) 参数:retval表示线程退出状态,通常NULL
1. 测试代码:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int func(int a)
{pthread_exit(NULL);
}void *tfn(void *arg)
{int i;i = (int)arg;sleep(i);if(i == 2)func(888);printf("I'am %dth thread, Thread_ID = %lu\n", i+1, pthread_self());pthread_exit(NULL);
}int main()
{int n = 5, i;pthread_t tid;for(i = 0; i < n; ++i) {pthread_create(&tid, NULL, tfn, (void*)i);}sleep(i);printf("I am main, and I am not a process, I'am a thread!\n""main_thread_ID = %lu\n", pthread_self());return 0;
}
输出结果:
2. 测试代码:
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>int func(int a)
{return 0;
}void *tfn(void *arg)
{int i;i = (int)arg;sleep(i);if(i == 2)func(888);printf("I'am %dth thread, Thread_ID = %lu\n", i+1, pthread_self());pthread_exit(NULL);
}int main()
{int n = 5, i;pthread_t tid;for(i = 0; i < n; ++i) {pthread_create(&tid, NULL, tfn, (void*)i);}sleep(i);printf("I am main, and I am not a process, I'am a thread!\n""main_thread_ID = %lu\n", pthread_self());return 0;
}
输出结果:
五、pthread_join函数
int pthread_join(pthread_t thread, void **retval);返回值:若成功,返回0,否则,返回错误编号
参数:
- thread:线程ID(【注意】:不是指针);retval:存储线程结束状态
注意:
- 调用该函数的线程将挂起等待,直到id为thread的线程终止状态。thread线程以不同的方法终止,通过pthread_join得到的终止状态是不同的,总结如下:
- 如果thread线程通过return返回,retval所指向的单元存放的是thread线程函数的返回值。
- 若果thread线程被别的线程调用pthread_cancel异常终止掉,retval指向单元里存放的是常数PTHREAD_CANCELED。
1. 测试代码:
#include<pthread.h>
#include<stdlib.h>typedef struct
{int a;int b;
} exit_t; void *tfn(void *arg)
{exit_t *ret;ret = (exit*)malloc(sizeof(exit_t));ret->a = 100;ret->b = 300;pthred_exit((void *) ret);
}
int main()
{pthread_t tid;exit_t *retval;pthread_create(&tid, NULL, tfn, NULL);pthread_join(tid, (void**)&retval); /*调用pthread_join可以获取线程的退出转态*/ printf("a = %d, b = %d\n", retval->a, retval->b);return 0;}
输出结果:
2. 测试代码:
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>typedef struct {int ch;int var;char str[64];
}exit_t;void *thrd_func(void *arg)
{exit_t *retval = (exit_t *)arg;retval->ch = 'm';retval->var = 200;strcpy(retval->str, "my thread\n");pthread_exit((void*) retval);
}
int main()
{pthread_t tid;int ret;exit_t *retval = (exit_t *)malloc(sizeof(exit_t));printf("In main 1: thread id = %lu, pid = %u\n", pthread_self(), getpid());ret = pthread_create(&tid, NULL, thrd_func, (void*)retval);if(ret != 0) {fprintf(stderr, "pthread_create error: %s\n", strerror(ret));exit(1);}pthread_join(tid, (void**)&retval);printf("ch = %c, var = %d, str = %s\n", retval->ch, retval->var, retval->str);free(retval);pthread_exit((void *)1);
}
输出结果:
测试代码:
#include<stdio.h>
#include<string.h>
#include<pthread.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>typedef struct {int ch;int var;char str[64];
}exit_t;void *thrd_func(void *arg)
{exit_t *retvar = (exit_t *)malloc(sizeof(exit_t));retvar->ch = 'm';retvar->var = 200;strcpy(retvar->str, "my thread\n");pthread_exit((void*) retvar);
}
int main()
{pthread_t tid;int ret;exit_t *retval;printf("In main 1: thread id = %lu, pid = %u\n", pthread_self(), getpid());ret = pthread_create(&tid, NULL, thrd_func, NULL);if(ret != 0) {fprintf(stderr, "pthread_create error: %s\n", strerror(ret));exit(1);}pthread_join(tid, (void**)&retval);printf("ch = %c, var = %d, str = %s\n", retval->ch, retval->var, retval->str);free(retval);pthread_exit((void *)1);
}
输出结果:
3. 测试代码:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>int var = 100;void *tfn(void *arg)
{int i;i = (int) arg;sleep(i);if(i == 1) {var = 333;printf("var = %d\n", var);return (void*) var;} else if(i == 3) {var = 777;printf("I'm %dth pthread, pthread_id = %lu\n var = %d\n", i+1, pthread_self(), var);pthread_exit((void*)var); } else {printf("I'm %dth pthread, pthread_id = %lu\n var = %d\n", i+1, pthread_self(), var);pthread_exit((void*)var);}return NULL;
}int main()
{int i;pthread_t tid[5];int *ret[5];for(i = 0; i < 5; ++i) {pthread_create(&tid[i], NULL, tfn, (void*)i);}for(i = 0; i < 5; ++i) {pthread_join(tid[i], (void**)&ret[i]);printf("----------%d's ret = %d\n", (int)ret[i]); }printf("I'm main pthread tid = %lu\t var = %d\n", pthread_self(), var);sleep(i);return 0;
}
输出结果: