判断网站cms门户网站的基本功能
线程
1.线程的概念:
线程是进程中的⼀个执行单元,负责当前进程中程序的执行,⼀个进程中至少有⼀个线程
 ⼀个进程中是可以有多个线程
 多个线程共享同一个进程的资源,每个线程参与操作系统的统一调度
 可以简单理解: 进程 = 进程资源 + 主线程 + 子线程+…
2.线程与进程
线程与进程区别:
- 内存空间:
 
- 一个进程中多个线程共享一个内存空间
 - 多个进程拥有独立的内存空间
 
- 进程/线程间通讯:
 
- 线程间通讯方式简单
 - 线程间通讯方式复杂
 
并发操作,线程比进程更节约资源
 总结:
 联系紧密的任务在并发时优先选择多线程,如果任务之间比较独立,在并发时建议选择多进程。
3.线程资源
- 共享进程的资源:
 
- 同一块地址空间
 - 文件描述符表
 - 每种信号的处理方式(如:SIG_DFL,SIG_IGCN或者自定义 的信号优先级)
 - 当前工作目录
 - 用户id和组id
 
- 独立的资源
 
- 线程栈
 - 每个线程都有私有的上下文信息
 - 线程ID
 - 寄存器的值
 - errno变量
 - 信号屏蔽以及调度优先级
 
4 .线程相关的命令
在 Linux 系统有很多命令可以查看进程,例如 pidstat 、top 、ps ,也可以查看一个进程下的线程
 一、pidstat
 ubuntu下安装 sysstat工具后,可以支持 pidstat
sudo apt install sysstat
选项
-t:显示指定进程所关联的线程
-p:指定进程pid
 
示例:使用 pidstat 命令查看某一个进程下的线程
- step 1 : 运行 sem 程序,此程序包含两个进程

 - step 2 : 查看 sem进程所对应的 id
 - step 3 : 使用 pidstat 命令查看相应进程的线程

 
可以看到当前这个进程包含1个线程,只有3027 主线程
二、top 命令
 top 命令查看某一个进程下的线程,需要用到 -H 选项在结合 -p 指定 pid
 示例:使用 top 命令查看某一个进程下的线程
top -H -p 3027 
 

 三、ps命令
 ps 命令结合 -T 选项就可以查看某个进程下所有线程
 
5 . 创造线程
创建线程调用 pthread_create 函数
1.函数头文件
#include <pthread.h>
2.函数原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg);
3.函数功能
创建一个子线程
4.函数参数
thread:线程ID变量指针
attr:线程属性,默认属性可设置为NULL
start_routine:线程执行函数
arg:线程执行函数的参数
5.函数返回值
成功:返回 0
失败:返回 错误码
 
Tips:
- typedef unsigned long int pthread_t;
 - 一旦子线程创建成功,则会被独立调度执行,并且与其他线程并发执行
 - 在编译时需要链接 -lpthread[Compile and link with -pthread]
 
问题:
- 在编译时出现下面的错误
implicit declaration of function ‘pthread_create’
解决办法:pthread库不是Linux系统默认的库,编译的时候需要加上库 -lpthread
2.2. 程序执行的结果中只打印了 tid,子线程没有执行
原因是子线程还没有来得及执行,主线程已经结束,导致其他子线程都必须结束
解决办法:保证主线程不先于子线程结束 
6.线程的等待、退出和分离
一、线程退出
 线程退出使用 pthread_exit 函数
函数头文件
#include <pthread.h>
函数原型
void pthread_exit(void *retval);
函数功能
让线程退出,并返回值
函数参数
retval:线程返回值,通过指针传递
函数返回值
成功:返回 0
失败:返回 -1
 
Tips:
- 当主线程调用pthread_exit函数时,进程不会结束,也不会导致其他子线程退出
 - 任何线程调用exit函数会让进程结束
 
二、线程等待
 主线程需要等待子线程退出,并释放子线程资源
 线程等待调用 pthread_join函数,会阻塞调用线程
1.函数头文件
#include <pthread.h>
2.函数原型
int pthread_join(pthread_t thread, void **retval);
3.函数功能
等待子线程退出,并释放子线程资源
4.函数参数
thread:线程 ID
retval:获取线程退出值的指针
5.函数返回值
成功:返回0
失败:返回错误码
 
三、线程分离
 线程分为可结合的与可分离的
- 可结合
 
- 可结合的线程能够被其他线程收回其资源和杀死;在被其他线程回收之前,它的存储器资源(如栈)是不释放的。
 - 线程创建的默认状态为可结合的,可以由其他线程调用 pthread_join函数等待子线程退出并
释放相关资源 
- 可分离
 
- 不能被其他线程回收或者杀死的,该线程的资源在它终止时由系统来释放。
 
- 线程分离调用 pthread_detach 函数
注意:线程分离函数不会阻塞线程的执行 
1.函数头文件
#include <pthread.h>
2.函数原型
int pthread_detach(pthread_t thread);
3.函数功能
设置在线程退出后,由操作系统自动释放该线程的资源
4.函数参数
thread:线程ID
5.函数返回值
成功:返回0
失败:返回-1
 
7.示例:
创造两个线程,并使线程分离:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
// 线程执行函数
void* do_thread_function(void* args)
{printf("do thread ....\n");pthread_exit(NULL);
}
int main()
{pthread_t thread_id_a,thread_id_b;int result = pthread_create(&thread_id_a,NULL,do_thread_function,NULL);if(result!=0){fprintf(stderr,"pthread error:%s\n",strerror(result));exit(EXIT_FAILURE);}printf("threadA id is %ld\n",thread_id_a);pthread_detach(thread_id_a);result = pthread_create(&thread_id_b,NULL,do_thread_function,NULL);if(result!=0){fprintf(stderr,"pthread error:%s\n",strerror(result));exit(EXIT_FAILURE);	}printf("threadB id is %ld\n",thread_id_b);pthread_detach(thread_id_b);while(1);return 0;
}
