Download presentation
Presentation is loading. Please wait.
Published by亦讨 仰 Modified 8年之前
1
多线程编程 Linux 下线程 概述 linux 线程 实现
2
1 、 Linux 下线程 概述 进程是系统中程序执行和资源分配的基 本单位。每个进程有自己的数据段、代码 段和堆栈段。 线程通常叫做轻型的进程。线程是在共 享内存空间中并发执行的多道执行路径, 他们共享一个进程的资源。 因为线程和进程比起来很小,所以相对 来说,线程花费更少的 CPU 资源。
3
用户地址空间 线程一线程二 线程三 进 程进 程 图 1 进程与线程的关系
4
线程按照其调度者可分为用户级线程和内核级线 程两种。 ( 1 )用户级线程 主要解决的是上下文切换的问题,其调度算法和 调度过程全部有用户决定。 ( 2 )内核级线程 有内核调度机制实现。 现在大多数操作系统都采用用户级线程和内核级 线程并存的方法。用户级线程可与内核级线程实现 “ 一对一 ” , “ 一对多 ” 的对应关系。
5
2 、 linux 线程实现 以下线程均为用户级线程。在 linux 中, 一般采用 Pthread 线程库实现线程的访问与 控制,由 POSIX 提出,具有良好的可移植 性。
6
2.1 线程创建与退出 创建线程使用 pthread_create 函数。在线程创 建以后,就开始运行相关的线程函数。线程退出 时使用函数 pthread_exit, 是线程的主动行为。注 意进程退出时使用 exit 函数,线程中用 pthread_exit 替代 exit 。 由于一个进程中的多个线程共享数据段,因 此通常在线程退出后,退出线程所占用的资源并 不会随线程结束而释放。所有需要 pthread_join 函数来等待线程结束,类似于 wait 系统调用。
7
创建进程: #include pthread_create(pthread_t *thread, pthread_attr_t *attr, void *(*start_routine)(void *), void *arg) thread :线程标识符 attr :线程属性设置 start_routine :线程函数起始地址 arg :传递给 start_routine 的参数
8
进程退出: #include pthread_exit( void *retval ) retval : pthread_exit 调用者线程的返回 值,可由其他函数和 pthread_join 来检测获 取。
9
等待进程退出: #include pthread_join( pthread_t *th , void **thread_return ) th :等待线程的标识符 thread_return :用户定义指针,用来存储 被等待线程的返回值 线程实例见: thread.c
10
2.2 修改线程属性 在 thread_creat 函数中有设置线程属性 参数,这些属性包括绑定属性、分离属性、 堆栈地址、堆栈大小、优先级。系统默认 属性为非绑定、非分离、缺省 1M 的堆栈、 与父进程同样级别的优先级。 分别介绍绑定属性和分离属性。
11
1 、绑定属性 在 linux 系统中,可实现一个用户级线程 与一个内核级线程相对应的 “ 一对一 ” 线程机 制。绑定属性是指一个用户级线程固定的 分配给一个内核级线程。非绑定属性则是 指用户级线程与内核级线程的关系不是始 终固定的,而是由系统来控制分配。
12
2 、分离属性 分离属性是用来决定一个线程以什么样 的方式来终止自己。在非分离情况下,当 一个线程结束时,它所占用的系统资源并 没有完全释放,也没有真正终止。只有当 pthread_join() 函数返回时,该线程才释放 自己占用的资源。而在分离情况下,一个 线程结束时会立即释放它所占用的资源。
13
3 、属性设置 属性设置是由一定函数来完成的,通常调用 pthread_attr_init 函数进行初始化。设置绑定属性的 函数为 pthread_attr_setscope, 设置分离属性的函数 是 pthread_attr_setdetachstate, 设置线程优先级的 相关函数 pthread_attr_getschdparm (获取线程优 先级)和 pthread_attr_setschedparam (设置线程 优先级)。在设置完成属性后,调用 pthread_creat 函数创建线程。
14
线程属性初始化: #include int pthread_attr_init (pthread_attr_t *attr) attr :线程属性 返回值:成功 0 ,错误 -1 。
15
设置绑定属性: #include pthread_attr_setscope(pthread_attr_t *attr, init scope) attr :线程属性 scope : PTHREAD_SCOPE_SYSTEM( 绑 定 ) PTHREAD_SCOPE_PRCESS( 非绑 定 ) 返回值:成功 0 ,错误 -1 。
16
设置分离属性 : #include pthread_attr_setsetdetachstate(pthread_attr_t *attr, init detachstate) attr :线程属性 detachstate : PTHREAD_CREAT_DETACHED( 分离 ) PTHREAD_CREAT_JOINABLE( 非分离 ) 返回值:成功 0 ,错误 -1 。
17
获取线程优先级: #include int pthread_attr_getschedparam (pthread_attr_attr *attr, struct sched_param *param) attr :线程属性 param :线程优先级 返回值:成功 0 ,错误 -1 。
18
设置线程优先级: #include int pthread_attr_setschedparam (pthread_attr_attr *attr, struct sched_param *param) attr :线程属性 param :线程优先级 返回值:成功 0 ,错误 -1 。 线程实例见: pthread.c
19
2.3 mutex 互斥锁线程控制 mutex 是一种简单的加锁的方法来控制对 共享资源的访问。在同一时刻只能有一个 线程掌握某个互斥上的锁, 拥有上锁状态的 线程能够对共享资源进行访问。若其他线 程希望上锁一个已经被上了互斥锁的资源, 则该线程挂起,直到上锁的线程释放互斥 锁为止。
20
互斥锁的操作主要包括以下几个步骤: 互斥锁初始化: pthread_mutex_init 互斥锁上锁: pthread_mutex_lock 互斥锁判断上锁: pthread_mutex_trylock 互斥锁解锁: pthread_mutex_unlock 消除互斥锁: pthread_mutex_destroy
21
互斥锁可分为以下三种: 快速互斥锁: 递归互斥锁: 检错互斥锁: 这三种锁的主要区别在于其他未占有互斥锁的线 程在希望得到互斥锁时是否需要阻塞等待。 快速互斥锁是指调用线程会阻塞直到拥有互斥锁的线 程释放为止。 递归互斥锁能够成功返回并且增加调用线程在互斥上 加锁的次数。 检错互斥锁则为快速互斥锁的阻塞版本,他会立即返 回并得到一个错误。
22
互斥锁初始化: #include int pthread_mutex_init( pthread_mutex_t *mutex, constpthread_mutex_attr_t *mutexattr) Mutex :互斥锁 Mutexattr : PTHREAD_MUTEX_INITIALIZER: 创建快速互斥锁 PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP: 创建递归互斥锁 PTHREAD_REEORCHECK_MUTEX_INITIALIZER_NP: 创建检错互斥锁
23
互斥锁操作: #include int pthread_mutex_lock(pthread_mutex_t *mutex) int pthread_mutex_trylock(pthread_mutex_t *mutex) int pthread_mutex_unlock(pthread_mutex_t *mutex) int pthread_mutex_destroy(pthread_mutex_t *mutex) Mutex :互斥锁 返回值:成功 0 ,错误 -1 。 互斥锁实例见: mutex.c
24
2.4 信号量线程控制 信号量也就是操作系统中所用到的 PV 操作, 它广泛用于进程或线程间的互斥与同步。 PV 操作是对整数计数器信号量 sem 的操作。 一次 P 操作使 sem 减一,一次 V 操作使 sem 加一。 用于互斥时,几个进程(或线程)往往只设 置一个信号量 sem 。 用于同步时,往往设置多个信号量,并安排 不同的值了来实现它们之间的顺序执行。
25
开始 初始化信号量 V 操作 线程二执行 线程一执行 P 操作 结束 图 2 信号量互斥操作
26
开始 初始化信号量 V 操作 sem1V 操作 sem2 线程二执行 线程一执行 P 操作 sem1P 操作 sem2 结束 图 3 信号量同步操作
27
Linux 实现了 POSIX.1 的无名信号量,用于 线程的同步与互斥。信号量操作函数: sem_init: 用于创建一个信号量,并初始化它。 sem_wait 或 sem_trywait: 相当于 P 操作,它们 都能使信号量减一,两者区别在于当信号量小 于零时, sem_wait 会阻塞,而 sem_trywait 则 会立即返回。 sem_post: 相当于 V 操作,它将信号量的值加一 同时发出信号唤醒等待的进程。 sem_getvalue: 得到信号量的值。 sem_destroy: 删除信号量。 信号量实例见: sem_mutex.c sem_syn.c
Similar presentations