进程
系统中程序执行和资源分配的基本单位
每个进程有自己的数据段、代码段和堆栈段
在进行切换时需要有比较复杂的上下文切换
线程
减少处理机的空转时间,支持多处理器以及减少上下文切换开销, 比创建进程小很多
进程内独立的一条运行路线
处理器调度的最小单元,也称为轻量级进程
可以对进程的内存空间和资源进行访问,并与同一进程中的其他线程共享
线程
线程相关的执行状态和存储变量放在线程控制表内
一个进程可以有多个线程,有多个线程控制表及堆栈寄存器,共享一个用户地址空间
多线程同步问题
线程共享进程的资源和地址空间
任何线程对系统资源的操作都会给其他线程带来影响
线程函数介绍
获得线程ID:
pthread_t
pthread_self( );
线程ID比较:
int
pthread_equal( pthread_t tid1, pthread_t tid2);
返回值: 若相等泽返回非0值,若不相等则返回0
线程创建:
int
pthread_create( pthread_t *restrict tidp, const pthread_attr_t *restrict attr, void* (*start_rfn) (void *), void *arg);
返回值:若成功则返回0,否则返回错误编号
注意: pthread函数在调用失败时通常会返回错误码,它们并不像其他的POSIX函数一样设置error。每个线程提供error副本,只是为了与使用error的现有函数兼容。
在线程中,从函数返回错误码更为精确,不需要依赖那些随着函数执行不断变化的全局状态。
打印代码段:printf(“%s pid %u (0x%x) \n", s, (unsigned int) getpid(),
(unsigned int) pthread_self() );
linux新创建的线程和主线程的进程ID不是相同的,这是因为linux的线程是通过使用clone系统调用实现的。clone系统调用创建子进程,这个子进程可以共享父进程一定数
量的执行环境(如文件描述符和内存),这个数量是可配置的。
线程终止:
单个线程有以下三种方式退出:
1、线程只从启动例程中返回,返回值是线程的退出码。
2、线程可以被同一进程中的其他线程取消(pthread_canel( pthread_t tid)
3、线程可以调用 void pthread_exit( void * rval_ptr )
rval_ptr是一个无类型指针,可以通过调用pthread_join函数访问到这个指针。
等待线程:
int pthread_join( phtread_t tid, void **rval_ptr);
返回值:成功返回0,否则返回错误码
调用线程一直阻塞,直到指定的线程调用pthread_exit、从启动例程中返回或者被取消。如果线程从启动例程返回,rval_ptr将包含返回码,如果线程被取消,由rval_ptr指
定的内存单元设置为PTHREAD_CANCELED.
可以通过pthread_join自动吧贤臣处于分离状态,这时,调用pthread_join就好是被,返回EINVAL.
如果对返回值不感兴趣,可以把rval_ptr置为NULL。
线程取消:
int pthread_cancel( pthread_t tid )
返回值: 若成功则返回0,否则返回错误码
pthread_cancel函数回使得由tid标示的线程的行为表现为如同调用了参数为PTHREAD_CANCELED的pthread_exit函数。
线程可以选择忽略取消方式或者控制取消方式
线程清理处理程序:
void
phtread_cleanup_push( void (*rtn)(void *), void *arg);
void pthread_cleanup_pop( int execute );
线程分离:
默认情况下,线程的终止状态会保存到对该线程调用pthread_join,如果线程已经处于分离状态,线程的底层存储资源可以在线程终止时立即收回。当线程分离时,不能用
pthread_join函数等待它的终止状态。
int pthread_detach ( pthread_t tid );
线程同步:
1、互斥量
初始化:
直接设置为敞亮PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量)
可以通过调用pthread_mutex_init函数进行初始化。如果动态的分配互斥量,那么在释放内存之前需要调用pthread_mutex_detroy.
int pthread_mutex_init( pthread_mutex_t *mutex, pthread_mutexattr_t *attr)
int phtread_mutex_destroy( phtread_mutex_t *mutex )
锁操作:
int pthread_mutex_lock( pthread_mutex_t
*mutex)
int phtread_mutex_unlock( pthread_mutex_t
*mutex)
int pthread_mutex_trylock( pthread_mutex_t *mutex);
pthread_mutex_trylock尝试加锁,如果失败返回EBUSY
2、读写锁
初始化:
int pthread_rwlock_init( pthread_rwlock_t *rwlock, const phtread_rwlockattr_t *attr)
清理:
int pthread_rwlock_destroy( pthread_rwlock_t *rwlock)
锁操作:
int pthread_rwlock_rdlock( pthread_rwlock_t *rwlock)
int pthread_rwlock_wrlock( pthread_rwlock_t *rwlock)
int pthread_rwlock_unlock( pthread_rwlock_t *rwlock)
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock)
int pthread_rwlock_trywr
lock(pthread_rwlock_t *rwlock)
3、条件变量
条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定条件的发生。条件本身是由互斥量保护的,线程在改变条件变量钱必须首先锁住互斥量。
初始化:
条件变量类型可用pthread_cond_t表示,可以把常量PTHREAD_COND_INITIALIZER赋给静态分配的条件变量,动态分配时用pthread_cond_int函数初始化
int pthread_cond_init( pthread_cond_t *cond, pthread_condattr_t *attr)
int pthread_cond_destroy(pthread_cond_t *cond)
等待条件:
int pthread_cond_wait( pthread_cond_t *cond, pthread_mutex_t *mutex)
int pthread_cond_timewait(
pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *timeout)
调用者吧锁住的互斥量传给函数,函数吧调用线程放到条件的线程列表上,然后对互斥量解锁,这两个操作是原子操作。
通知线程条件满足:
int pthread_cond_signal( pthread_cond_t *cond)
int pthread_cond_broadcast( pthread_cond_t *cond)