2010年(30)
分类: LINUX
2010-07-06 10:40:30
进程是系统中程序执行和资源管理的基本单位,每个进程都拥有自已的数据段、代码段和堆栈段,而线程是进程的基本调度单位,它们共享进程的资源,如内存地址空间、文件描述符和信号处理等,与进程比较而言,线程的使用大大减少上下文切换的开销,对这些特性做以下总结:a) 调度,线程作为调度和分配的基本单位,进程作为拥有资源的基本单位b) 并发性,对于基于内核线程的LinuxThread而言,进程和线程都可以并发执行c) 拥有资源,进程是资源的拥有者,而线程是资源的使用者d) 系统开销,线程的系统开销远小于进程
1. 用户级线程2. 内核线程Linux2.4中所使用的LinuxThread是基于内核线程1:1模型,存在用户态管理线程(?)对线程之间进行管理。Linux2.6重写内核线程框架,使用NPTL(Native POSIX Thread Library)线程库,其与LinuxThread应用二进制兼容,但没有使用管理线程,线程的管理直接放在核内进行。
不管是LinuxThread还是NPTL,用户空间的线程操作都是使用POSIX的Pthread线程库,因此具有良好的兼容性。a) 线程的创建与退出
/*创建线程*/
int pthread_create((pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg))
/*线程退出,注意不能用exit,因为exit是使调用进程终止*/
void pthread_exit(void *retval)
/*线程同步机制,将当前线程挂起,等待线程的结束*/
int pthread_join((pthread_t th, void **thread_return))
a) 属性初始化
int pthread_attr_init(pthread_attr_t *attr)
b) 绑定属性Linux采用1:1的线程机制,所谓绑定属性就是指一个用户线程固定地分配给一个内核线程,因为CPU时间片的调度是面向内核线程的,因此且有绑定属性的线程可以保证在需要的时候总有一个内核线程与之对应。而非绑定属性就是指用户线程和内核线程的关系不是始终固定的,而是由系统来控制分配的。
int pthread_attr_setscope(pthread_attr_t *attr, int scope)
scope:
PTHREAD_SCOPE_SYSTEM //绑定
PTHREAD_SCOPE_PROCESS //非绑定
c) 分离属性分离属性是用来决定一个线程以什么样的方式来终止自已,在非分离情况下,当一个线程结束时,它所占用的系统资源并没有被释放,也就是没有真正的终止。只有当pthread_join函数返回时,创建的线程才能释放自已占用的系统资源。而在分离属性的情况下,一个线程结束时立即释放它所占用的系统资源。这里要注意的是,假如设置了一个线程的分离属性,而该线程运行又非常快,那么它可能在pthread_create函数返回之前就终止了,它终止后就可能将线程号和系统资源交给其它的线程使用,这时调用pthread_create的线程就得到了错误的线程号。
int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
detachstate:
PTHREAD_CREATE_DETACHED //分离
PTHREAD_CREATE_JOINABLE //非分离
由于多线程共享进程的地址空间,但线程间是并发调度的,因此,必需考虑到资源操作的唯一性问题.
POSIX线程同步方法主要有两种,分别是互斥锁和信号量.
a) mutex互斥锁
互斥锁使用一种简单的加锁方法来控制对共享资源的存取,这种锁有两种状态,分别是上锁和解锁,同一个时刻只有一个线程可以拥有该锁,当其它线程在试图访问一个已上锁的资源时会导致进程挂起,真到上锁的线程释放互斥锁时为止.
互斥锁包括以下操作:
- 初始化 pthread_mutex_init
- 上锁 pthread_mutext_lock
- 判断上锁 pthread_mutext_trylock (该操作不会导致线程挂起)
- 解锁 pthread_mutex_unlock
- 消除互斥锁 pthread_mutex_destroy
根据初始化参数不同,互斥锁可以细分以下三种锁:
- 快速互斥锁,调用线程会阻塞直至拥有互斥锁的线程解锁为止
- 递归互斥锁,能够成功返回,并增加调用线程在互斥上加锁的资数
- 检错互斥锁,是快速互斥锁的非阻塞版本,它会立即返回出错信息
b) 信号量
信号时使用PV原语在线程间进行互斥、同步操作.
PV原语是对整数计数器信号时sem的操作,P操作使sem减一,V操作使sem加一,当sem大于或等于0是,线程且有公共资源的访问权限,而若小于0,线程将阻塞直至信号量sem大于或等于0.如上所述,信号量主要用于互斥与同步操作.
如上图所示,当用于互斥操作时,通常只设置一个信号量sem,而当用于同步操作时,通常设置多个信号,并使用不同的初值实现顺序操作.
信号量包括以下操作:
- sem_init,创建并初始化信号量
- sem_wait,相当于P操作,阻塞线程
- sem_trywait,相当于P操作,不阻塞线程
- sem_post,相当于V操作,信号量值加一同时发出信号唤醒其它等待的线程
- sem_getvalue,得到信号量的值
- sem_destory,删除信号量