一、【线程与进程】
a>.进程技术优势:
(1)CPU时分复用,单核心CPU可以实现宏观上的并行
(2)实现多任务系统需求(多任务的需求是客观的)
b>.进程技术劣势
(1)进程间切换开销大
(2)进程间通信麻烦而且效率低
、线程
a>.线程技术保留了进程技术实现多任务的特性。
b>.线程的改进就是在线程间切换和线程间通信上提升了效率。
c>.多线程在多核心CPU上面更有优势。
【优势】:
(1)像进程一样可被OS调度
(2)同一进程的多个线程之间很容易高效率通信
(3)在多核心CPU(对称多处理器架构SMP)架构下效率最大化
(2)、【关系】:
0)但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。1) 简而言之,一个程序至少有一个进程,一个进程至少有一个线程.
2) 线程的划分尺度小于进程,使得多线程程序的并发性高。
3) 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
4) 线程在执行过程中与进程还是有区别的。每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
5) 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
6).线程是参与内核调度的最小单元,一个进程中可以有多个线程
(3)、【优缺点】
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源的管理和保护;而进程正相反。同时,线程适合于在SMP(对称多处理器架构)机器上运行,而进程则可以跨机器迁移。
二、线程常见函数
【action】:程序在编译时,一定要【gcc 文件名 -lpthread】添加动态链接库进行编译,否则编译可以通过,但是链接会出错。
1、线程创建与回收
(1)pthread_create 主线程用来创造子线程的
int pthread_create(pthread_t*thread, const pthread_attr_t *attr,
void*(*start_routine) (void *), void *arg);
4个参数:
第一个参数:指向线程标示符pthread_t的指针;
第二个参数:设置线程的属性【一般为NULL】
第三个参数:线程运行函数的起始地址
第四个参数:运行函数的参【一般为NULL】}
(2)pthread_join 主线程用来等待(阻塞)回收子线程
(3)pthread_detach 主线程用来分离子线程,分离后主线程不必再去回收子线程
unjoinable属性可以在pthread_create时指定,或在线程创建后在线程中pthread_detach自己, 如:pthread_detach(pthread_self()),将状态改为unjoinable状态,确保资源的释放。如果线程状态为 joinable,需要在之后适时调用pthread_join.
2、线程取消
(1)pthread_cancel 一般都是主线程调用该函数去取消(让它赶紧死)子线程
如果当前进程是不可取消的,则该函数无效。
(2)pthread_setcancelstate 可取消的状态
(1)子线程设置自己是否允许被取消并且将先前的状态返回到oldstate引用中。
“可取消性”状态的合法值分别是:
PTHREAD_CANCEL_ENABLE 和PTHREAD_CANCEL_DISABLE。
(2)查询当前线程的“可取消性”状态,即把第一个参数设为NULL
(3)pthread_setcanceltype 可取消的类型
设置当前线程的“可取消类型”,并且将先前的类型返回到oldtype引用中。
“可取消类型”的合法值分别是:
PTHREAD_CANCEL_DEFERRED :
(同步取消,取消的请求被放在队列中,直到线程到达某个点,才被取消。)
PTHREAD_CANCEL_ASYNCHRONOUS :
(异步取消,一个线程可以在任何时刻被取消。)
【action】:
“可取消性”和“可取消类型”存在于任意一个新建线程中,包括主线程,默认设置是PTHREAD_CANCEL_ENABLE 和 PTHREAD_CANCEL_DEFERRED。
3、线程函数退出相关
(1)pthread_exit与return退出
/****************************************************************/
线程退出函数【pthread join & pthreadexit】的区别:
pthread_join:一般是主线程来调用,用来等待子线程退出,因为是等待,所以是阻塞的,
一般主线程会依次join所有它创建的子线程。
pthread_exit:一般是子线程调用,用来结束当前线程。结束当前进程后,该线程不会释放所占用的堆和栈以及文件描述符,只有当调用了pthread join函数后,才会释放这些资源。
子线程可以通过pthread_exit传递一个返回值,而主线程通过pthread_join获得该返回值,从而判断该子线程的退出是正常还是异常。
/****************************************************************/
(2)pthread_cleanup_push
(3)pthread_cleanup_pop
pthread_cleanup_push & pthread_cleanup_pop这两个函数一般都是成对出现的
4、获取线程id
(1)pthread_self
Linux下获取线程有两种方法:
1)gettid或者类似gettid的方法
2)直接调用pthreadself()函数
(1)线程同步:
(1)为什么需要多线程实现
(2)问题和困难点是?
(3)理解什么是线程同步
3.7.4.3、信号量的介绍和使用
3.7.6.线程同步之互斥锁
3.7.6.1、什么是互斥锁
(1)互斥锁又叫互斥量(mutex)
(2)相关函数:pthread_mutex_initpthread_mutex_destroy
pthread_mutex_lockpthread_mutex_unlock
(3)互斥锁和信号量的关系:可以认为互斥锁是一种特殊的信号量
(4)互斥锁主要用来实现关键段保护
3.7.6.2、用互斥锁来实现上节的代码
注意:man 3 pthread_mutex_init时提示找不到函数,说明你没有安装pthread相关的man手册。安装方法:1、虚拟机上网;2、sudoapt-get install manpages-posix-dev
3.7.7.线程同步之条件变量
3.7.7.1、什么是条件变量
3.7.7.2、相关函数
pthread_cond_init pthread_cond_destroy
pthread_cond_wait pthread_cond_signal/pthread_cond_broadcast
3.7.7.3、使用条件变量来实现上节代码
3.7.7.4、线程同步总结