linux多线程程序设计
7
多线程创建的API
• • • 线程创建函数:pthread_create 等待指定的线程结束:pthread_join
IT Education & Training
获取自己线程ID函数:pthread_self 函数原形:pthread_t pthread_self (void); 线程退出函数: pthread_exit 函数原形:void pthread_exit (void *__retval)
9
线程的访问控制
IT Education & Training
线程共享进程的资源和地址空间时必须保持线程间资源访问的 唯一性问题: 解决问题的方法: 互斥锁 命名规则:pthread_mutex_***
条件变量 命名规则: pthread_cond_*** 信号量: 命名规则: sem_***
10
返回值:成功 0 失败 -1
6
多线程创建的API
• 等待指定的线程结束:pthread_join
IT Education & Training
函数原形:int pthread_join (pthread_t th, void **thread_return); ① th:等待线程的标识符 ② thread_return:用户定义的指针,存放被等待线程的返回值 返回值:成功 0 失败 -1
11
互斥锁主要的多线程API函数
•
IT Education & Training
• •
•
•
互斥锁初始化:pthread_mutex_init pthread_mutex_init (pthread_mutex_t *,__const pthread_mutexattr_t *) 销毁互斥锁:pthread_mutex_destroy int pthread_mutex_destroy (pthread_mutex_t *__mutex); 锁定互斥锁(阻塞):pthread_mutex_lock int pthread_mutex_lock (pthread_mutex_t *__mutex); 激活该产品 试图获得互斥锁(非阻塞):pthread_mutex_trylock int pthread_mutex_trylock (pthread_mutex_t *__mutex); 解锁互斥锁:pthread_mutex_unlock int pthread_mutex_unlock (pthread_mutex_t *__mutex)
5
多线程创建的API
• 线程创建函数:pthread_create
IT Education & Training
函数原形:int pthread_create (pthread_t * thread, pthread_attr_t * attr,void *(*start_routine) (void *),void *arg); ① thread:返回的线程标识符 ② attr:线程属性设置(NULL) ③ start_routine:线程函数的入口地址 ④ arg:传递给start_routine的参数
17
生产者、消费者问题
主程序、生产者线程、消费者线程流程图:
IT Education & Training
18
生产者、消费者问题
• 生产(post)、消费(get)流程图:
IT Education & Training
19
IT Education & Training
Thank you
谢谢
Neusoft Group Ltd.
•
8
多线程创建的API
试建立源文件,有如下要求:
IT Education & Training
(1)Main函数所在的线程:循环3次打印“This is main process.” (2)在main函数内创建一个线程,函数入口为thread,在这个 函数内循环三次打印“This is thread created by main.” (3)main函数所在的线程必须等到thread所在的线程结束后 才能结束。
14
信号量
IT Education & Training
• 信号量 (1)信号量(semaphore)是另一种加锁操作,与普通加锁 不同的是,信号量记录了一个空闲资源数值,信号量的值表 示了当前空闲资源实体数。 (2)信号量的数据类型为结构sem_t,本质上是一个非负的 长整数计数器,它被用来控制对公共资源的访问。 ----当可用公共资源增加时,调用函数sem_post()增加信号 量。只有当信号量值大于0时,才能使用公共资源。 ----使用后,调用函数sem_wait()减少信号量。当它变为0时, 进程将主动放弃处理器进入等待队列。
线程访问控制-互斥锁
IT Education & Training
• 互斥锁 互斥锁用来保证一段时间内只有一个线程在执行一段代码。 (1)必要性显而易见:假设多个线程向同一个文件顺序写入 数据,最后得到的结果一定是灾难性的。 (2)判断线程间是否需要互斥,关键是看线程间是否共享某 一公有资源。 (3)数据类型:pthread_mutex_t 。 (4)线程执行临界区程序的操作按下列步骤进行: ①关锁。先检查锁的状态,如为关闭状态,则等待其打开; 如已打开了,则将其关闭,继续执行②的操作。 ②执行临界区程序。 ③开锁。将锁打开,退出临界区。
20
12
条件变量
IT Education & Training
• 条件ห้องสมุดไป่ตู้量 (1)条件变量通过允许线程阻塞和等待另一个线程发送信号 的方法弥补了互斥锁的不足,它常和互斥锁一起使用。
(2)使用时,条件变量被用来阻塞一个线程,当条件不满足 时,线程往往解开相应的互斥锁并等待条件发生变化。 一旦其它的某个线程改变了条件变量,它将通知相应的条件 变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程 将重新锁定互斥锁并重新测试条件是否满足。
4
多线程创建的API
注意事项:
IT Education & Training
(1)编写源代码,如果需要调用线程函数,则必须包括头文件: #include<pthread.h> (2)在进行编译的时候需要使用参数:-lpthread
(3)变量类型pthread_t: pthread_t在头文件/usr/include/bits/pthreadtypes.h中定义 typedef unsigned long int pthread_t;
15
主要的多线程API函数
•
IT Education & Training
•
• •
初始化一个信号量:sem_init 函数原型为: extern int sem_init __P ((sem_t *__sem, int __pshared, unsigned int __value)); 增加信号量的值:sem_post 函数原形:sem_post( sem_t *sem ); 减少信号量的值:sem_ wait 函数原型:sem_wait( sem_t *sem ); 释放信号量:sem_ destroy 函数原型:sem_destroy(sem_t *sem) 用来释放信号量sem。
(3) 数据类型:pthread_cond_t 。
13
条件变量主要的多线程API函数
•
IT Education & Training
• •
•
•
条件变量初始化:pthread_cond_init int pthread_cond_init (pthread_cond_t * cond, __const pthread_condattr_t * cond_attr) 销毁条件变量:pthread_cond_destroy int pthread_cond_destroy (pthread_cond_t *__cond) 等待条件变量(阻塞):pthread_cond_wait extern int pthread_cond_wait (pthread_cond_t *__restrict__cond, pthread_mutex_t *__restrict __mutex) 指定时间到达前等待条件变量:pthread_cond_timedwait int pthread_cond_timedwait (pthread_cond_t *__restrict __cond, pthread_mutex_t *__restrict __mutex, __const struct timespec *__restrict __abstime) 唤醒线程等待条件变量:pthread_cond_signal extern int pthread_cond_signal (pthread_cond_t *__cond);
不和进程比较,还有以下优点:
提高应用程序响应 使多CPU系统更加有效 改善程序结构
3
多线程的创建
一、线程的创建和退出
IT Education & Training
线程的创建:确定调用该线程函数的入口点。调用函数 pthread_create()。 线程的退出: (1)当该函数运行完之后,该线程就自动退出了。 (2)调用线程退出函数:pthread_exit() 。 注意:不要随意调用exit退出函数。
16
生产者、消费者问题
IT Education & Training
• 生产者、消费者问题的定义 生产者消费者问题:生产者要不断将数据放入共享的缓冲, 消费者要不断从缓冲取出数据。缓冲区满时,消费者必须等 生产者取走数据后才能再放新数据(不覆盖数据);缓冲区 空时,消费者必须等生产者放入新数据后才能去取(不重 复)。