Linux 多线程 – 线程异步与同步机制 I. 同步机制 线程间的同步机制主要包括三个: 互斥锁: 以排他的方式,防止共享资源被并发访问; 互斥锁为二变量, 状态为0-开锁、1-上锁; 开锁必须由上锁的线程执行,不受其它线程干扰. 条件变量: 满足某个特定条件时,可通过条件变量通知其它线程do-something; 必须与互斥锁*联合使用,单独无法执行. 读写锁: 针对多读者,少写者的情况设定 允许多读,但此时不可写; 唯一写,此时不可读. 函数的头文件为: 1. 互斥锁 操作流程: I. 创建互斥锁 II. 申请锁:若可用,立刻占用;否则,阻塞等待 III. do-something IV. 释放锁 V. 销毁锁 以下是互斥锁的基本操作函数: 功能 函数 参数 返回值 说明 初始化锁 int pthread_mutex_init( pthread_mutex_t *mutex, const pthread_mutexattr_t *attr) 1. mutex: 欲建立的互斥锁 2.attr:属性,一般为NULL 成功:0 失败:非零值 阻塞申请锁 int pthread_mutex_lock( pthread_mutex_t *mutex) mutex:互斥锁 成功:0 失败:非零值 若未申请到, 阻塞等待 非阻塞申请 int pthread_mutex_trylock( pthread_mutex_t *mutex) mutex:互斥锁 成功:0 失败:非零值 若未申请到, 返回错误 释放锁 int pthread_mutex_unlock( pthread_mutex_t *mutex) mutex:互斥锁 成功:0 失败:非零值 销毁锁 int pthread_mutex_destroy( pthread_mutex_t *mutex) mutex:互斥锁 成功:0 失败:非零值 2. 条件变量 注意,条件变量必须与互斥锁共同使用; 以下是条件变量的基本操作函数: 功能 函数 参数 返回值 说明 初始化锁 int pthread_cond_init( pthread_cond_t *cond, const pthread_condattr_t *attr) 1. cond: 欲建立的条件变量 2.attr:属性,一般为NULL 成功:0 失败:非零值 等待条件变量 int pthread_cond_wait( pthread_cond_t *cond, pthread_mutex_t *mutex) 1.cond:条件变量 2.mutex:互斥锁 成功:0 失败:非零值 阻塞等待 隐含释放申请到的互斥锁 限时等待条件变量 int pthread_cond_timewait( pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *time) 3.time:等待过期的绝对时间 从1970-1-1:0:0:0起 成功:0 失败:非零值 struct timespec{long ts_sec; long ts_nsec} 单一通知 int pthread_cond_signal( pthread_cond_t *cond) cond:条件变量 成功:0 失败:非零值 唤醒等待cond的第一个线程 隐含需要的互斥锁 广播通知 int pthread_cond_broadcast( pthread_cond_t *cond) cond:条件变量 成功:0 失败:非零值 唤醒所有等待cond的线程 隐含需要的互斥锁 销毁条件变量 int pthread_cond_destroy( pthread_cond_t *cond) cond:条件变量 成功:0 失败:非零值 3. 读写锁 读写基本原则: 若当前线程读数据,则允许其他线程读数据,但不允许写 若当前线程写数据,则不允许其他线程读、写数据 以下是基本的操作: 功能 函数 参数 返回值 说明 初始化锁 int pthread_rwlock_init( pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr) 1. rwlock: 欲建立的读写锁 2.attr:属性,一般为NULL 成功:0 失败:非零值 阻塞申请读锁 int pthread_rwlock_rdlock( pthread_rwlock_t *rwlock) rwlock:读写锁 成功:0 失败:非零值 若未申请到, 阻塞等待 非阻塞申请 int pthread_rwlock_tryrdlock( pthread_rwlock_t *rwlock) rwlock:读写锁 成功:0 失败:非零值 若未申请到, 返回错误 阻塞申请写锁 int pthread_rwlock_wrlock( pthread_rwlock_t *rwlock) rwlock:读写锁 成功:0 失败:非零值 若未申请到, 阻塞等待 非阻塞申请写锁 int pthread_rwlock_trywrlock( pthread_rwlock_t *rwlock) rwlock:读写锁 成功:0 失败:非零值 若未申请到, 返回错误 释放锁 int pthread_mutex_unlock( pthread_rwlock_t *rwlock) rwlock:读写锁 成功:0 失败:非零值 销毁锁 int pthread_rwlock_destroy( pthread_rwlock_t *rwlock) rwlock:读写锁 成功:0 失败:非零值 4. 线程信号量 线程信号量类似进程的信号量,主要是使得多个线程访问共享资源时,顺序互斥访问。 与互斥锁的区别在于: 互斥锁:只有一个bool类型的值,只允许2个线程进行排队; 信号量:允许多个线程共同等待一个共享资源 函数如下: 功能 函数 参数 返回值 说明 创建信号量 int sem_init(sem_t *sem, int pshared, unsigned int value) 1. sem:信号量地址; 2. pshared:是(!=0)否(0)为共享信号量 3. value:信号量初值 0: 成功 -1: 失败 P操作(阻塞) int sem_wait(sem_t *sem) sem:信号量地址 0: 成功 -1: 失败 P操作(非阻塞) int sem_trywait(sem_t *sem) sem:信号量地址 0: 成功 -1: 失败 P操作(时间) int sem_timedwait(sem_t *sem, const struct timespec *abs_timeout) 1. sem:信号量地址 2. abs_timeout:超时时间 0: 成功 -1: 失败 struct timespec 见下面 V操作 int sem_post(sem_t *sem) sem:信号量地址 0: 成功 -1: 失败 信号量值 int sem_getvalue(sem_t *sem, int *sval) 1. sem:信号量地址 2. sval: 将信号量值放到该地址 0: 成功 -1: 失败 删除信号量 int sem_destroy(sem_t *sem) sem:信号量地址 0: 成功 -1: 失败 II. 异步机制 – 信号 线程的异步机制只有,类似于线程的信号。 线程信号具备以下特点 任何线程都可以向其它线程(同一进程下)发送信号; 每个线程都具备自己独立的信号屏蔽集,不影响其它线程; 线程创建时,不继承原线程的信号屏蔽集; 同进程下,所有线程共享对某信号的处理方式,即一个设置,所有有效; 多个线程的程序,向某一个线程发送终止信号,则整个进程终止 信号的基本操作如下: 功能 函数 参数 返回值 说明 安装信号 sighandler_t signal( int signum, sighandler_t handler) 1.signum:信号值 2.handler:信号操作 详情参见: http://www.cnblogs.com/Jimmy1988/p/7575103.html 发送信号 int pthread_kill( pthread_t threadid, int signo 1.threadid: 目标线程id 2.signo:信号值 成功:0 失败:非零值 若signo=0, 检测该线程是否存在, 不发送信号 设置屏蔽集 pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset) 1.how:如何更改信号掩码 2.newmask:新的信号屏蔽集 3.原信号屏蔽集 成功:0 失败:非零值 how值: 1.SIG_BLOCK:添加新掩码 2.SIG_UNBLOCK:删除新掩码 3.SIG_SETMASK:设置新掩码完全替换旧值 也可以参考这篇博客:https://www.cnblogs.com/coding-my-life/p/4782529.html III、示例代码 1.同步机制: 1). 互斥锁: 两个线程: 读线程:从中读取数据,并存储 写线程:从存储buffer中读取数据并显示 2). 条件变量: 生产者和消费者问题: 生产者: 向仓库生产数据(大小可任意设定),当满时,阻塞等待仓库有空闲(由消费者消费完后通知) 消费者: 从仓库读数据,若仓库为空,则阻塞等待,当生产者再次生产产品后通知 3). 读写锁: 四个线程:两读两写; 多进程可同时读,但此时不可写; 只有一个线程可写,其它线程等待该线程写完后执行响应的读/写操作 2. 异步机制 – 信号: 本程序包括两个线程: 线程1安装SIGUSR1,阻塞除SIGUSR2外的所有信号; 线程2安装SIGUSR2,不阻塞任何信号 操作流程: 1- 线程1、2安装信号; 2- 主线程发送SIGUSR1和SIGUSR2至线程1和线程2; 3- 线程1接收到除SIGUSR2之外的信号,阻塞不执行;当收到SIGUSR2后,执行对应操作; 4- 线程2接收到SIGUSR1和SIGUSR2后,分别执行对应操作 5- 主线程发送SIGKILL信号,结束整个进程
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/66840.html