07_线程
WP:light weight process),在Linux环境下线程的本质仍是进程,进程必须至少包含一个线
程。线程 依赖于 进程,线程共享进程的资源,进程结束 当前进程的所有线程 都将立即结束。线程共享资源1) 文件
描述符表2) 每种信号的处理方式3) 当前工作目录4) 用户ID和组ID 内存地址空间 (。text/。dat
a/。bss/heap/共享库)线程非共享资源1) 线程id2) 处理器现场和栈指针(内核栈)3) 独立的栈空
间(用户空间栈)4) errno变量5) 信号屏蔽字6) 调度优先级线程的优缺点优点: Ø 提高程序并发性 Ø
开销小 Ø 数据通信、共享数据方便缺点: Ø 库函数,不稳定 Ø 调试、编写困难、gdb不支持 Ø 对信号支
持不好 优点相对突出,缺点均不是硬伤。Linux下由于实现方法导致进程、线程差别不是很大。知识点2【线程的AP
I】1、查看线程号1 #include <pthread。h>2 pthread_t pthread_self
(void);功能:获取线程号。参数:无返回值:调用线程的线程 ID2、创建线程1 #include <pth
read。h>2 int pthread_create(pthread_t *thread,3 const p
thread_attr_t *attr,4 void *(*start_routine)(void *),5
void *arg );功能:创建一个线程参数:thread:线程标识符地址。attr:线程属性结构体地址,通
常设置为 NULL。start_routine:线程函数的入口地址。arg:传给线程函数的参数。返回值:成功:
0失败:非 0案例1:创建线程 每个线程有独立的线程函数1 #include <stdio。h>2 #incl
ude <pthread。h>3 #include <unistd。h>4 void *pthread_fun
01(void *arg)5 {6 int i = 0;7 while (1)8 {9 printf("%s‐
‐‐‐‐‐‐i=%d\n", (char *)arg, i++);10 sleep(1);11 }12 ret
urn NULL;13 }14 void *pthread_fun02(void *arg)15 {16 in
t i = 0;17 while (1)18 {19 printf("%s‐‐‐‐‐‐‐i=%d\n", (c
har *)arg, i++);20 sleep(1);21 }22 return NULL;23 }24 i
nt main(int argc, char const *argv[])25 {26 //创建两个线程27
pthread_t tid1, tid2;28 pthread_create(&tid1, NULL, pth
read_fun01, "任务A");29 pthread_create(&tid2, NULL, pthre
ad_fun02, "任务B");3031 getchar();32 return 0;33 }案例2:创建线
程 每个线程共用的同一线程函数1 #include <stdio。h>2 #include <pthread。
h>3 #include <unistd。h>4 void *pthread_fun(void *arg)5
{67 int i = 0;8 while (1)9 {10 printf("%s‐‐‐‐‐‐‐i=%d\n"
, (char *)arg, i++);11 sleep(1);12 }1314 return NULL;15
}1617 int main(int argc, char const *argv[])18 {19 //创
建两个线程20 pthread_t tid1, tid2;21 pthread_create(&tid1, N
ULL, pthread_fun, "任务A");22 pthread_create(&tid2, NULL,
pthread_fun, "任务B");2324 getchar();25 return 0;26 }3、回
收线程资源(阻塞)pthread_join函数:带阻塞1 #include <pthread。h>2 int
pthread_join(pthread_t thread, void **retval);功能:等待线程结束
(此函数会阻塞),并回收线程资源,类似进程的 wait() 函数。如果线程已经结束,那么该函数会立即返回。参数
:thread:被等待的线程号。retval:用来存储线程退出状态的指针的地址返回值:成功:0失败:非 0案例
1:回收线程资源1 #include <stdio。h>2 #include <pthread。h>3 #in
clude <unistd。h>4 void *pthread_fun01(void *arg)5 {67 i
nt i = 0;8 for (; i < 5; i++)9 {10 printf("%s‐‐‐‐‐‐‐i=%
d\n", (char *)arg, i++);11 sleep(1);12 }1314 return NUL
L;15 }16 void *pthread_fun02(void *arg)17 {1819 int i =
0;20 for (; i < 3; i++)21 {22 printf("%s‐‐‐‐‐‐‐i=%d\n"
, (char *)arg, i++);23 sleep(1);24 }2526 return NULL;27
}2829 int main(int argc, char const *argv[])30 {31 //创
建两个线程32 pthread_t tid1, tid2;33 pthread_create(&tid1, N
ULL, pthread_fun01, "任务A");34 pthread_create(&tid2, NUL
L, pthread_fun02, "任务B");3536 //回收线程资源(带阻塞的)37 pthread_
join(tid1, NULL);38 printf("tid1结束了\n");39 pthread_join
(tid2, NULL);40 printf("tid2结束了\n");4142 return 0;43 }案
例2:回收线程资源 并获取线程返回值的值1 #include <stdio。h>2 #include <pth
read。h>3 #include <unistd。h>4 void *pthread_fun01(void
*arg)5 {67 int i = 0;8 for (; i < 5; i++)9 {10 printf("
%s‐‐‐‐‐‐‐i=%d\n", (char *)arg, i++);11 sleep(1);12 }131
4 return (void *)"任务A";15 }16 void *pthread_fun02(void
*arg)17 {1819 int i = 0;20 for (; i < 3; i++)21 {22 pri
ntf("%s‐‐‐‐‐‐‐i=%d\n", (char *)arg, i++);23 sleep(1);24
}2526 return (void *)"任务B";27 }2829 int main(int argc,
char const *argv[])30 {31 //创建两个线程32 pthread_t tid1, t
id2;33 pthread_create(&tid1, NULL, pthread_fun01, "任务A"
);34 pthread_create(&tid2, NULL, pthread_fun02, "任务B");
3536 //回收线程资源(带阻塞的)37 void *p1 = NULL;38 pthread_join(t
id1, &p1);39 printf("tid1结束了,返回值为%s\n", (char *)p1);40
pthread_join(tid2, &p1);41 printf("tid2结束了, 返回值为%s\n",
(char *)p1);4243 return 0;44 }4、pthread_detach分离线程(不阻塞)
将线程的回收工作 分离出去 线程结束时,线程由系统回收资源。pthread_detach函数:1 #inclu
de <pthread。h>2 int pthread_detach(pthread_t thread);功能
:使调用线程与当前进程分离,分离后不代表此线程不依赖与当前进程,线程分离的目的是将线程资源的回收工作交由系统自
动来完成,也就是说当被分离的线程结束之后,系统会自动回收它的资源。所以,此函数不会阻塞。参数:thread:线
程号。返回值:成功:0失败:非01 #include <stdio。h>2 #include <pthread
。h>3 #include <unistd。h>4 void *pthread_fun01(void *arg
)5 {67 int i = 0;8 for (; i < 5; i++)9 {10 printf("%s‐‐
‐‐‐‐‐i=%d\n", (char *)arg, i++);11 sleep(1);12 }1314 re
turn (void *)"任务A";15 }1617 int main(int argc, char con
st *argv[])18 {19 //创建两个线程20 pthread_t tid1, tid2;21 pt
hread_create(&tid1, NULL, pthread_fun01, "任务A");22 //线程
分离(不带阻塞)23 pthread_detach(tid1);2425 //主函数 也是一个线程26 int
i = 0;27 while (1)28 {29 printf("%s‐‐‐‐‐‐‐i=%d\n", "任务
B", i++);30 sleep(1);31 }3233 return 0;34 }知识点3【线程的取消和退
出】(了解)1、线程退出1 #include <pthread。h>2 void pthread_exit(v
oid *retval);3 功能:4 退出调用线程。一个进程中的多个线程是共享该进程的数据段,因此,通常线程
退出后所占用的资源并不会释放。5 参数:6 retval:存储线程退出状态的指针。7 返回值:无1 #incl
ude <stdio。h>2 #include <pthread。h>3 #include <unistd。h
>4 void *pthread_fun01(void *arg)5 {67 int i = 0;8 whil
e (1)9 {10 printf("%s‐‐‐‐‐‐‐i=%d\n", (char *)arg, i++);
11 if (i == 5)12 pthread_exit(NULL); //线程结束13 sleep(1);
14 }1516 return NULL;17 }1819 int main(int argc, char c
onst *argv[])20 {21 //创建两个线程22 pthread_t tid1;23 pthrea
d_create(&tid1, NULL, pthread_fun01, "任务A");24 //线程分离(不
带阻塞)25 pthread_join(tid1, NULL);26 printf("任务A结束了\n");2
7 return 0;28 }2、线程的取消取消自己、也可以取消当前进程的其他线程。1 #include <p
thread。h>2 int pthread_cancel(pthread_t thread);3 功能:4
杀死(取消)线程5 参数:6 thread : 目标线程ID。7 返回值:8 成功:09 失败:出错编号杀死线
程也不是立刻就能完成,必须要到达取消点。 取消点:是线程检查是否被取消,并按请求进行动作的一个位置。通常是一些
系统调用。1 #include <stdio。h>2 #include <pthread。h>3 #inclu
de <unistd。h>4 void *pthread_fun01(void *arg)5 {67 int
i = 0;8 while (1)9 {10 printf("%s‐‐‐‐‐‐‐i=%d\n", (char
*)arg, i++);11 sleep(1); //取消点12 }1314 return NULL;15 }
1617 int main(int argc, char const *argv[])18 {19 //创建两
个线程20 pthread_t tid1;21 pthread_create(&tid1, NULL, pth
read_fun01, "任务A");22 //线程分离(不带阻塞)23 pthread_detach(tid
1);2425 printf("5秒后结束任务A\n");26 sleep(5);27 pthread_can
cel(tid1);2829 getchar();30 return 0;31 }知识点4【线程的属性】(了解
)1 typedef struct2 {3 int etachstate; //线程的分离状态4 int sc
hedpolicy; //线程调度策略5 struct sched_param schedparam; //线
程的调度参数6 int inheritsched; //线程的继承性7 int scope; //线程的作用域
8 size_t guardsize; //线程栈末尾的警戒缓冲区大小9 int stackaddr_set;
//线程的栈设置10 void* stackaddr; //线程栈的位置11 size_t stacksiz
e; //线程栈的大小12 } pthread_attr_t;案例1:使用线程的属性 完成线程分离以前的方案:
1 pthread_t tid1;2 pthread_create(&tid1,NULL, pthread_f
un01, "任务A");3 //线程分离(不带阻塞)4 pthread_detach(tid1);如果线程先
结束 pthread_detach后执行 就存在问题。现在的方案:创建线程的时候 通过线程属性 设置线程分离,
就定义保存 先分离 后执行线程(解决了上面的问题)初始化的函数为pthread_attr_init,这个函数必
须在pthread_create函数之前调用。1 初始化线程属性函数:2 int pthread_attr_i
nit(pthread_attr_t *attr);3 函数返回值:成功:0;失败:错误号45 销毁线程属性所
占用的资源函数:6 int pthread_attr_destroy(pthread_attr_t *attr
);7 函数返回值:成功:0;失败:错误号线程分离状态的函数: 设置线程属性,分离or非分离1 int pth
read_attr_setdetachstate(pthread_attr_t *attr, int deta
chstate);获取程属性,分离or非分离1 int pthread_attr_getdetachstate
(pthread_attr_t *attr, int *detachstat);参数: