线程
线程是一个轻量级的进程,本质还是进程(Linux下)(其实可以把它就当成一个回调函数)
一个进程分为N个线程,最少有一个线程(例如hello world可以成为单线程程序)
线程是调用CPU调度的单位(进程是分配系统资源),线程是最小的执行单位,进程是最小的分配资源单位
线程有独立的PCB,但没有独立的地址空间(共享地址空间)而进程有独立的地址空间独立的PCB.(线程依赖于进程,所有线程共享进程资源)
线程也叫轻量级进程(light weight process),有自己的PCB,创建线程使用的底层函数和进程是一样的都是clone
在内核角度进程线程是一样的,都有各自的PCB,但线程PCB中指向内存资源的三级页表是相同的
进程可以蜕变为线程(创建线程就会由原来的进程蜕变成线程)
线程可以看成是寄存器于栈的集合,栈的大小默认为8M实际上会多分配一些
三级页表,就是PCB中的一块区域(页面)里面存储的指针指针一块区域(页表),页表中还是指针指向一块区域(页目录),页目录中是映射的物理地址(内存单元)
理论上来说,线程越多的进程,执行的越快但是有一个峰值(因为可以更多的获取CPU)
*windows下和Linux下线程并不一样
windows以线程为主,Linux下原本没有线程这一说,只是为了迎合windows而加入的(对于开发人员)
线程共享资源
文件描述符表(线程间通信不需要借助mmap,管道等)
信号处理方式(线程彼此不独立,一个信号哪个线程抢到哪个线程接收(信号是共享),但是mask(文件掩码)是独立的可以程序员指定)不过只是可以,理论上可以尽量别作死
当前工作目录
用户ID, 组ID
内存地址空间
线程非共享资源
线程ID
寄存器计算的值,栈指针(内核栈(保存寄存器的临时值)),无论用户栈还是内核栈都是不共享的
errno变量(他是要给全局变量,但是也不共享)
线程可以通过调度改变执行顺序
线程优缺点
优点
提高程序并发性
开销小(一块内存区)
数据通信共享方便(共享PCB)
缺点
库函数,没有系统函数稳定性好
难写,难调试,GDB不支持(因为出现的太晚)
对信号支持不友好
优点突出,高并发,小开销就足够了,缺点程序员可以克服
pthread_self(获得线程ID),PS查看的是线程号两个不一样
头文件
#include <pthread.h>
原型
pthread_t pthread_self(void);
返回值
成功返回线程ID,该函数不会失败
pthread_t(是无符号整形,有些系统中可能是一个结构体)
线程ID只是用来在进程中标识身份的,线程号是给CUP用的
pthread_create(创建一个新线程)
头文件
#include <pthread.h>
原型
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
返回值
成功返回0,失败返回errno
参数
thread 传出参数(传出线程ID)
attr(线程属性,可以设置线程状态,一般传null(表示默认属性))
start_routine(回调函数)
arg(回调函数的参数,没有参数null)