一 线程(也称为轻量级的进程)数据结构
1.一、线程基本特色多线程
a)线程依赖于进程而存在,在一个进程里面开出的多个线程共享同一进程空间,这样利用多线程实现多任务时,就能避免由于大量频繁的进程间切换而带来的开销。并发
b)每一个线程也一样有一个task_truct结构体来描述,可是共享同一进程的全部线程共享入口地址异步
c)进程与线程都参与统一的内核调度(切换)。函数
d)线程的本质就是指针函数。post
1.二、线程好处spa
1)大大提升了进程间的切换效率线程
2)避免了没必要要的TLB和cache刷新,节省了空间的消耗指针
1.三、线程的实现rest
1)不禁内核实现,而是由第三方线程库实现的,编译时须要链接才行
2)同一进程内的全部线程都会共享进程的哪些资源呢?
a)指令代码
b)静态数据(主要是用于线程间通讯用的全局变量)
c)进程打开的全部的文件描述符
d)进程的当前工做目录
e)进程的实际用户ID和有效用户ID
f)实际组ID和有效组ID
3)每一个线程的私有资源有哪些?
a)线程ID(TID)
b)本身的PC(程序计数器值)和相关的状态寄存器(存放该线程被切换时的状态)
c)本身的局部变量(每一个线程其实就是一个函数),每一个线程都会从进程栈中开出本身的
线程栈(也可称为线程函数栈)
d)本身的错误号errno
e)本身的信号掩码(屏蔽字,起初是继承进程(主线程)的),和未决信号集(继承于主线程,可是会被当即清空)
f)有本身的执行状态
4)线程实现过程
a)建立线程,pthread_create函数
b)控制线程,pthread_join,pthread_detach,pthread_cancle,pthread_exit等函数
5)线程的资源保护
咱们知道,对于进程来讲资源保护是自然的,由于它们拥有独立虚拟内存空间,互相不能互访,这也致使相互通讯也很不容易。可是对于同一进程内的多个线程来讲,因为它们共享进程的虚拟内存地址,所以它们相互之间能够很容易地进行资源的共享,可是资源间的保护却成为了一个问题。线程资源保护机制有:
a)无名信号量(进程用的是有名信号量或称为系统V信号量)
b)线程间的互斥锁
c)条件变量(一种线程间的异步通讯机制,相似于进程间的信号通讯)
6)注意,若是主线程先死,那么全部次线程都会跟着死调,因此任何线程调了exit函数后整个进程将会结束
二 线程与进程
进程是程序执行时的一个实例,即它是程序已经执行到何种程度的数据结构的聚集。从内核的观点看,进程的目的就是担当分配系统资源(CPU时间、内存等)的基本单位。
线程是进程的一个执行流,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。一个进程由几个线程组成(拥有不少相对独立的执行流的用户程序共享应用程序的大部分数据结构),线程与同属一个进程的其余的线程共享进程所拥有的所有资源。
"进程——资源分配的最小单位,线程——程序执行的最小单位"
进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不一样执行路径。线程有本身的堆栈和局部变量,但线程没有单独的地址空间,一个线程死掉就等于整个进程死掉,因此多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行而且又要共享某些变量的并发操做,只能用线程,不能用进程。
具体异同看下表:
三 相关函数
线程建立函数
intpthread_create(pthread_t*thread,constpthread_attr_t*attr,
void*(*start_routine)(void*),void*arg);
线程等待函数:阻塞等待线程结束,结束后由主回收线程的资源
intpthread_join(pthread_tthread,void**retval);
线程分离函数:分离后,资源在线程结束时本身释放,不有主线程回收
intpthread_detach(pthread_tthread);//这个函数和pthread_join两者只能有一个被用
主动取消线程函数
int pthread_cancel(pthread_tthread);·取消是不是使能设置函数:默认状况是使能
线程属性设置函数
线程属性有哪些:
a)绑定属性:用户线程和内核服务线程是否绑定(default:非绑定),cpu时间片的调度是面向内核线程实现的
b)分离属性:线程结束时,线程资源由谁回收,设置了分离,就由本身释放,未设置分离,资
源由等待线程(join函数等待)回收,(default:非分离),分离属性也可由前
面的pthread_detach函数来设置
c)堆栈的地址和堆栈的大小:线程的堆栈其实就是函数的堆栈,是从进程的堆栈中刮分出来的,
默认状况下,线程具体的堆栈地址由内核决定,堆栈大小默认1M,固然我也能够认为的更改它
d)线程的优先级:因为线程是与它的生父进程(主线程)同样统一地参与内核的
调度器的调度,因此存在着调度优先级的问题,默认状况是他和生父进程有着一样的优先级别
e)通常状况下,咱们都采用默认设置便可
线程属性设置函数
a)线程属性初始化函数
intpthread_attr_init(pthread_attr_t*attr);
b)线程属性删除函数:删除为属性设置,恢复内核原有默认的属性设置,
防止永远的穿改了默认的属性设置
intpthread_attr_destroy(pthread_attr_t*attr);c)设置绑定函数
intpthread_attr_setscope(pthread_attr_t*attr,intscope);//设置intpthread_attr_getscope(pthread_attr_t*attr,int*scope);//获取
d)设置分离属性
intpthread_attr_setdetachstate(pthread_attr_t*attr,intdetachstate);//设置
intpthread_attr_getdetachstate(pthread_attr_t*attr,int*detachstate);//获取
e)设置堆栈属性
/*设置*/
intpthread_attr_setstack(pthread_attr_t*attr,void*stackaddr,size_tstacksize)
/*获取*/intpthread_attr_getstack(pthread_attr_t*attr,void**stackaddr,size_t*stacksize)
f)设置优先级属性
/*设置*/
intpthread_attr_setschedparam(pthread_attr_t*attr,conststructsched_param*param);
/*获取*/
intpthread_attr_getschedparam(pthread_attr_t*attr,structsched_param*param);
设置互斥锁相关的函数
互斥锁初始化函数
intpthread_mutex_init(pthread_mutex_t*restrictmutex,constpthread_mutexattr_t*restrictattr);
互斥锁直接初始化,只能初始化,不能赋值,由于pthread_mutex_t是结构体类型
pthread_mutex_tmutex=PTHREAD_MUTEX_INITIALIZER;
互斥锁销毁函数
intpthread_mutex_destroy(pthread_mutex_t*mutex);
加锁解锁函数
阻塞解锁:intpthread_mutex_lock(pthread_mutex_t*mutex);
非阻塞加锁:intpthread_mutex_trylock(pthread_mutex_t*mutex);·解锁:intpthread_mutex_unlock(pthread_mutex_t*mutex);
互斥锁属性设置函数
·互斥锁属性初始化和删除
/*属性初始化*/
intpthread_mutexattr_init(pthread_mutexattr_t*attr);/*互斥所属性删除:相似线程的属性删除*/
intpthread_mutexattr_destroy(pthread_mutexattr_t*attr);
互斥锁类型设置和获取
互斥锁类型分类:
PTHREAD_MUTEX_DEFAULT:快速互斥锁(或叫阻塞互斥锁),默认此种锁,统一把锁,不能屡次加锁,已经解开了的锁也不能再次解锁,这些都会出错返回
PTHREAD_MUTEX_ERRORCHECK:检错互斥锁,快速互斥锁的费阻塞版本
PTHREAD_MUTEX_RECURSIVE:递归互斥锁,同一把锁可屡次枷锁,每加一次锁,锁的链接计数加1,解锁时的解锁顺序与加锁顺序相反,每解一次链接技术减1,加过多少次锁,就必须接多少次
intpthread_mutexattr_settype(pthread_mutexattr_t*attr,inttype);//设置
intpthread_mutexattr_gettype(constpthread_mutexattr_t*restrictattr,int*restricttype);//获取
设置线程信号量相关的函数
初始化函数
intsem_init(sem_t*sem,intpshared,unsignedintvalue);
删除函数
intsem_destroy(sem_t*sem);
P操做:等资源
intsem_wait(sem_t*sem);//阻塞等待资源
intsem_trywait(sem_t*sem);//非阻塞等待资源/*可设置超时,阻塞超过必定时间,超时不在阻塞*/
intsem_timedwait(sem_t*sem,conststructtimespec*abs_timeout);
v操做:释放资源
intsem_post(sem_t*sem);·信号量无属性设置
条件变量设置
初始化和删除函数/*初始化条件变量*/
intpthread_cond_init(pthread_cond_t*restrictcond,constpthread_condattr_t*restrictattr);
intpthread_cond_destroy(pthread_cond_t*cond);//删除条件变量
pthread_cond_tcond=PTHREAD_COND_INITIALIZER;//直接变量初始化(不能赋值)
条件变量发送信号函数
/*唤醒所有由于该条件变量而休眠的线程*/
intpthread_cond_broadcast(pthread_cond_t*cond);/*唤醒其中一个由于该条件变量而休眠的线程*/intpthread_cond_signal(pthread_cond_t*cond);3)等待条件变量信号函数
/*可设置超时,等待超时,则超时返回*/
intpthread_cond_timedwait(pthread_cond_t*restrictcond,pthread_mutex_t*restrictmutex,conststructtimespec*restrictabstime);
/*一直等待,知道到等到唤醒信号*/
intpthread_cond_wait(pthread_cond_t*restrictcond,pthread_mutex_t*restrictmutex);·