linux环境C编程课件LINUXC编程第六讲

上传人:E**** 文档编号:91242556 上传时间:2019-06-26 格式:PPT 页数:21 大小:301.50KB
返回 下载 相关 举报
linux环境C编程课件LINUXC编程第六讲_第1页
第1页 / 共21页
linux环境C编程课件LINUXC编程第六讲_第2页
第2页 / 共21页
linux环境C编程课件LINUXC编程第六讲_第3页
第3页 / 共21页
linux环境C编程课件LINUXC编程第六讲_第4页
第4页 / 共21页
linux环境C编程课件LINUXC编程第六讲_第5页
第5页 / 共21页
点击查看更多>>
资源描述

《linux环境C编程课件LINUXC编程第六讲》由会员分享,可在线阅读,更多相关《linux环境C编程课件LINUXC编程第六讲(21页珍藏版)》请在金锄头文库上搜索。

1、LINUX C编程,教师:中国地质大学 朱静,第七讲 线程,线程概念的引入 线程及其管理 线程创建 线程终止,并发执行的进程具有两个基本的属性: (1)进程既是一个拥有资源的独立单位,它可独立分配虚地址空间、主存和其它系统资源; (2)进程又是一个可独立调度和分派的基本单位。 这两个基本属性使进程成为并发执行的基本单位。在一些OS中,象大多数UNIX系统、Linux等,进程同时具有这两个属性。而另一些OS中,象WinNT、Solaris、OS2、Mac OS等,这两个属性由OS独立处理。 为了区分两个属性,资源拥有单元称为进程(或任务),调度的单位称为线程。,线程概念的引入,【线程的定义】:

2、进程内一个CPU执行单元或一个可调度实体。 线程只拥有一点在运行中必不可省的资源(线程ID,程序计数器、一组寄存器、栈和线线程私有数据),但它可与同属一个进程的其它线程共享进程拥有的全部资源。 在多线程的操作系统中,处理机调度的基本单位是线程。一个进程可以有多个线程,而且至少有一个可执行线程。,线程概念的引入,【进程和线程的关系】: 线程是进程的一个组成部分。每个进程创建时通常只有一个线程,需要时可创建其他线程。 进程的多线程都在进程的地址空间活动。 资源是分给进程的,不是分给线程的。线程在执行中需要资源时,可从进程资源中划分。 处理机调度的基本单位是线程,线程之间竞争处理机。真正在CPU上运

3、行的是线程。 线程在执行时,需要同步。,线程及其管理,进程 控制块 PCB,用户地址空间,线程 控制块 TCB 用户栈 核心栈,线程 控制块 TCB 用户栈 核心栈,线程 控制块 TCB 用户栈 核心栈,多线程进程模块,线程A,线程B,线程C,多线程是OS在一个进程内支持多个线程的能力。,多线程模型,单线程与多线程的比较,Thread Control Block,User Stack,User Stack,Kernel Stack,Kernel Stack,User Address Space,User AddressSpace,Process Control Block,Process Co

4、ntrol Block,Thread,Single-Threaded Process Model,Multithreaded Process Model,Thread Control Block,User Stack,Kernel Stack,Thread,Thread Control Block,User Stack,Kernel Stack,Thread,【线程的特征】: 创建线程比创建进程快,且节省开销。 一个进程至少要有一个可执行线程,可以有多个线程。 参与竞争处理机的基本调度单位是线程。 线程调度程序是内核的主要成分,也是其主要功能之一。 一个线程可以创建它所需的其他线程。 一个线程

5、可以有就绪,等待,运行等状态。 方便而有效地实现并行性:进程可创建多个线程来执行同一个程序的不同部分。 用线程实现并行性比用进程实现更方便更有效。,线程及其管理,每个线程有一个线程ID 线程ID和进程ID的区别: 进程ID在整个系统中是唯一的,但线程ID只在它所属的进程环境中有效 线程ID相关系统调用 #include pthread_t pthread_self(void);获得线程自身ID int pthread_equal(pthread_t tid1,pthread_t tid2);比较两个线程ID是否相等,线程标识,#include pthread_t pthread_create(

6、pthread_t *restrict tidp,const pthread_attr_t *restrict attr,void *(*start_rtn)(void),void *restrict arg); 调用成功返回由tidp指向的线程ID,attr参数用于指定各种不同的线程属性,attr设为NULL表示创建默认属性的线程。新建线程从start_rtn函数的地址开始运行(该函数只有一个无类型指针参数arg,如果需要向start_rtn函数传递的参数不止一个,那么需要把这些参数放到一个结构中,并把这个结构的地址作为arg参数传入)。 调用失败返回错误码。 例:打印线程ID thread

7、id.c,线程创建,如果进程中的任一线程调用了exit,Exit或_exit,整个进程将会终止。 如果信号的默认动作是终止进程,那么把该信号发送到线程会终止整个进程 单个线程可以通过下列三种方式在不终止整个进程的情况下终止: 1,线程只是从例程中返回; 2,线程可以被同一进程中的其他线程取消; 3,线程调用pthread_exit;,线程终止,#include void pthread_exit(void *rval_ptr); rval_ptr是一个无类型指针,与传递给pthread_create的单个参数类似。进程中的其他线程可以通过调用pthread_join函数访问到这个指针。 int

8、 pthread_join(pthread_t thread,void *rval_ptr); 调用这个函数的线程将一直阻塞,到指定的线程调用pthread_exit、从启动例程中返回或被取消。 例:获得线程退出状态 exitstatus.c,线程终止,当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图。当某个线程修改变量,而其他线程也可以读取或修改这个变量时,就需要对这些线程进行同步,以确保它们在访问变量的存储内容时不会访问到无效的值。 线程可以通过使用pthread的互斥接口保护数据,确保同一时间只有一个线程访问数据。 互斥变量用pthread_mutex_t数据类型来表示

9、。在使用互斥变量以前,必须首先对它进行初始化:可以通过把它设置为常量PTHREAD_MUTEX_INITIALIZER(静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过malloc函数),那么在释放内存前需要调用pthread_mutex_destroy,线程同步,#include int pthread_mutex_init(prhtread_mutex *restrict mutex,const pthread_mutexattr_t *restrict attr); 要用默认的属性初始化互斥量,只需把attr设为NULL

10、。 int pthread_mutex_destroy(pthread_mutex_t *mutex); 对互斥量进行加锁和解锁 int pthread_mutex_lock(pthread_mutex_t *mutex); int pthread_mutex_trylock(pthread_mutex_t *mutex); int pthread_mutex_unlock(pthread_mutex_t *mutex);,线程同步,对互斥量进行加锁要调用pthread_mutex_lock;如果互斥量已经上锁,则调用线程将阻塞直到互斥量被解锁。 对互斥量进行解锁要调用pthread_mute

11、x_unlock; 如果线程不希望被阻塞,可以使用pthread_mutex_trylock尝试对互斥量进行加锁,如果调用pthread_mutex_trylock时互斥量牌末锁住状态,那么pthread_mutex_trylock将锁住互斥量,不会出现阻塞并返回0,否则pthread_mutex_trylock调用失败,不能锁住互斥量,返回EBUSY。 例:使用互斥量保护数据结构 mutex1.c,线程同步,如果线程试图对同一个互斥量加锁两次,它自身就会陷入死锁状态。 使用互斥量时,其他更不明显的方式也能产生死锁,例如:程序中使用多个互斥量时,如果允许一个线程一直占有一个互斥量,并且在试图锁

12、住第二个互斥量时处于阻塞状态,但占有第二个互斥量的线程也在试图锁住第一个互斥量,这时就会发生死锁。 死锁避免: 1,可以通过小心地控制互斥量加锁的顺序来避免死锁的发生。 2,使用pthread_mutex_trylock避免死锁。,避免死锁,通过小心地控制互斥量加锁的顺序来避免死锁的发生。 所有线程按相同的顺序对互斥量进行加锁。只有在一个线程试图以与另一个线程相反的顺序锁住互斥量时,才可能出现死锁。 使用pthread_mutex_trylock避免死锁。 如果已经占有某些锁而且pthread_mutex_trylock返回成功,线程才可以前进,如果pthread_mutex_trylock不

13、能获取锁,可以先释放已经占有的锁,做好清理工作,过一段时间重新尝试。 例: 使用多个互斥量时避免死锁 mutex2.c,避免死锁,读写锁(也叫共享-独占锁)与互斥量相似,但读写锁允许更高的并行性。 读写锁可以有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是可以有多个线程同时占有读模式的读写锁。 与互斥量一样,读写锁使用之前必须初始化,释放它们的底层内存之前必须先销毀。 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, attr); int pthread_rwlock_d

14、estroy(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_trtwrlock(pthread_

15、rwlock_t *rwlock); 例:使用读写锁. rwlock.c,读写锁,条件变量是线程可用的另一种同步机制。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。 int pthread_cond_init(); int pthread_cond_destroy(); int pthread_cond_wait(); int pthread_cond_timewait(); int pthread_cond_signal(); int pthread_cond_broadcast();,条件变量,条件变量是线程可用的另一种同步机制。条件变量与互斥量一起使用时,允许线程以无竞争的方式等待特定的条件发生。 int pthread_cond_init(); int pthread_cond_destroy(); int pthread_cond_wait(); int pthread_cond_timewait(); int pthread_cond_signal(); int pthread_cond_broadcast();,线程,

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号