线程同步API及它们的属性
头文件:<pthread.h> 编译记得加 -lpthread库
1:互斥锁(mutex)
1.1:互斥锁API
数据类型:pthread_mutex_t
// 初始化一个互斥锁
int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
or pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;// 互斥锁的默认属性 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER 等价于 pthread_mutex_init(&mutex, NULL)
-------------------------------------------------------------------------------------
// 销毁一个互斥锁
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_timedlock(pthread_mutex_t *mutex, const struct timespec *time);
-------------------------------------------------------------------------------------
// 释放一个互斥锁
int pthread_mutex_unlock(pthread_mutex_t *mutex);
以上函数返回值:成功0,失败设置errno
1.2:互斥锁的属性
数据类型:pthread_mutexattr_t
1.2.0 互斥锁属性之初始化
// 初始化一个互斥锁属性
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
-------------------------------------------------------------------------------------
// 销毁一个互斥锁属性
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
-------------------------------------------------------------------------------------
1.2.1 互斥锁属性之pshared 属性
// 设置pshared属性
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr, int pshared);
pshared取值:
:PTHREAD_PROCESS_SHAREAD --> 表示此属性的互斥锁放在共享内存中,可以被多个进程中的线程共享
:PTHREAD_PROCESS_PRIVATE --> 表示此属性的互斥锁只能被和创建此锁的线程在同一进程中的其他线程共享(推荐默认值)
// 获取pshared属性
int pthread_mutexattr_getpshared(pthread_mutexattr_t *attr, int *pshared);
1.2.2 互斥锁属性之robust属性
// 设置robust属性(此属性主要使用在锁位于进程间使用的情况)
/*
robust的取值:
1:PTHREAD_MUTEX_STALLED --> 当一个进程在拥有锁的时候异常挂掉,这时另一个进程企图获得锁将一直阻塞,出现
死锁(deadlock)的情况.
2:PTHREAD_MUTEX_ROBUST --> 这时企图获得锁的进程pthread_mutex_lock将返回EOWNERDEAD而不是0,它提示占用
此锁的进程已经挂掉,需要恢复锁,所以如果使用了mutex的robust属性且设置为PTHREAD_MUTEX_ROBUST,在获得锁时要处理pthread_mutex_lock返回的
三种情况(不是PTHREAD_MUTEX_ROBUST属性只需处理两种,0成功,其它失败),三种情况是:
A:调用成功,锁不用恢复(返回0)
B:调用成功,锁需要恢复(返回EOWNERDEAD)
C:调用失败(返回其它)
对于返回情况B,首先应该调用pthread_mutex_consistent函数先恢复锁,再解锁,最后获得锁执行随后的代码.如果未调用pthread_mutex_consistent函数恢复过锁,
而在B情况后直接解锁,之后获得锁,那么pthread_mutex_lock将返回ENOTRECOVERABLE,提示此锁已经不能再继续使用,这时就只能pthread_mutex_destroy锁之后重新初始
化锁再使用.
注:互斥锁的robust属性一定程度上提供了死锁的一种解决方案.
*/
int pthread_mutexattr_setrobust(pthread_mutexattr_t *attr, int robust);
// 获得robust属性
int pthread_mutexattr_getrobust(pthread_mutexattr_t *attr, int *robust);
// 恢复锁的状态
int pthread_mutex_consistent(pthread_mutex_t *mutex);
1.2.3 互斥锁属性之type属性
// 设置type属性
/*
type的四种取值:
1:PTHREAD_MUTEX_NORMAL --> 属性默认值
2:PTHREAD_MUTEX_ERRORCHECK --> 执行锁的错误检查,如死锁,不占用时解锁,已解锁时解锁都会返回错误值提示
3:PTHREAD_MUTEX_RECURSIVE --> 允许你在同一线程下连续加锁而不造成死锁(强调是同一线程下),你必须有同次
数的解锁之后才能释放此锁,条件变量中的互斥锁不要使用此属性,会造成条件的不一致.
4:PTHREAD_MUTEX_DEFAULT --> ?
*/
int pthread_mutexattr_settype(pthread_mutexattr_t *attr, int type);
// 获得type属性
int pthread_mutexattr_gettype(pthread_mutexattr_t *attr, int *type);
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
2:读写锁(rwlock)
2.1:读写锁API
数据类型:pthread_rwlock_t
// 初始化读写锁
int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
or pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;// 读写锁的默认属性
pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER 等价于 pthread_rwlock_init(&rwlock, NULL)
-------------------------------------------------------------------------------------
// 销毁读写锁
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
-------------------------------------------------------------------------------------
// 读方式获取锁
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
// 非阻塞读方式获取锁
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
// 带有超时的读方式获取锁
int pthread_rwlock_timedrdlock(pthread_rwlock_t *rwlock, const struct timespec *time);
-------------------------------------------------------------------------------------
// 写方式获取锁
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
// 非阻塞写方式获取锁
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
// 带有超时的写方式获取锁
int pthread_rwlock_timedwrlock(pthread_rwlock_t *rwlock, const struct timespec *time);
-------------------------------------------------------------------------------------
// 解锁
int pthread_rwlock_unlock(pthread_rwlock_t *rwlock);
以上函数返回值:成功0,失败设置errno
注:读写锁适合使用在临界资源读频率远高于写频率的情况下。
当临界资源位于读锁定情况下,读方式获取锁会成功,写方式获取锁会被阻塞(如有一个线程以写方式获取锁时被阻塞,内核通常会阻塞之后的以读方式获取锁的进程,防止临界资源一直被读锁定占用)
当临界资源位于写锁定情况下,读或写方式获取锁都是被阻塞
2.2:读写锁的属性
数据类型:pthread_rwlockattr_t
2.2.0:读写锁属性之初始化
// 初始化读写锁属性
int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
// 销毁读写锁属性
int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
2.2.1:读写锁属性之pshared属性<读写锁只有pshared属性可设置>
// 设置pshared属性
int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *attr, int pshared);
pshared取值:
:PTHREAD_PROCESS_SHAREAD --> 表示此属性的读写锁放在共享内存中,可以被多个进程中的线程共享
:PTHREAD_PROCESS_PRIVATE --> 表示此属性的读写锁只能被和创建此锁的线程在同一进程中的其他线程共享(推荐默认值)
// 获取pshared属性
int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *attr, int *pshared);
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
3:条件变量
3.1:条件变量API
数据类型:pthread_cond_t
// 初始化条件变量
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr);
-------------------------------------------------------------------------------------
// 销毁条件变量
int pthread_cond_destory(pthread_cond_t *cond);
-------------------------------------------------------------------------------------
// 等待条件变量为真
int pthread_cond_wait(pthread_cond_t *cond, pthrad_mutex_t *mutex);
这个函数会阻塞进程,直到接收到pthread_cond_signal或者pthread_cond_broadcast函数的信号,传递给函数的mutex是一个已被锁住的mutex.
函数有两个原子操作:
:unlock mutex(解锁的目的是使其它线程有机会获得锁来改变'条件'),阻塞等待获得信号
:获得信号后lock mutex,函数返回
-------------------------------------------------------------------------------------
// 带超时的wait
int pthread_cond_wait(pthread_cond_t *cond, pthrad_mutex_t *mutex);
超时是指一个绝对值,即目前时间+超时时间
例:
void maketimeout(struct timespec *tsp, long minutes)
{
struct timeval now;
gettimeofday(&now, NULL);
tsp->tv_sec = now.tv_sec;
tsp->tv_nsec = now.tv_usec * ;// 1微妙 = 1000纳秒
tsp->tv_sec += minutes * ;
} struct timeval { struct timespec{
time_t tv_sec; //秒 time_t tv_sec; //秒
long tv_usec;//微妙 long tv_nsec; //纳秒
}; };
-------------------------------------------------------------------------------------
// 通知某一个线程条件满足
int pthread_cond_signal(pthread_cond_t *cond);
// 通知所有等待线程条件满足(惊群)
int pthread_cond_broadcast(pthread_cond_t *cond);
以上函数返回值:成功0,失败设置errno
3.2:条件变量的属性
数据类型:pthread_condattr_t
3.2.0:条件变量属性之初始化
// 初始化条件变量属性
int pthread_condattr_init(pthread_condattr_t *attr);
// 销毁条件变量属性
int pthread_condattr_destroy(pthread_condattr_t *attr);
3.2.1:条件变量属性之pshared
// 设置pshared属性
int pthread_condattr_setpshared(pthread_condattr_t *attr, int pshared);
pshared取值:
:PTHREAD_PROCESS_SHAREAD --> 表示此属性的条件变量放在共享内存中,可以被多个进程中的线程共享
:PTHREAD_PROCESS_PRIVATE --> 表示此属性的条件变量只能被和创建此锁的线程在同一进程中的其他线程共享(推荐默认值)
// 获取pshared属性
int pthread_condattr_getpshared(pthread_condattr_t *attr, int *pshared);
-------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------
4:自旋锁
数据类型:pthread_spinlock_t
操作API:
// 初始化自旋锁
int pthread_spin_init(pthread_spinlock_t *spin, int pshared);
自旋锁的属性只有一个值,即pshared,它有两种取值:
1:PTHREAD_PROCESS_SHAREAD --> 表示此属性的自旋锁放在共享内存中,可以被多个进程中的线程共享
2:PTHREAD_PROCESS_PRIVATE --> 表示此属性的自旋锁只能被和创建此锁的线程在同一进程中的其他线程共享(此属性的默认值)
-------------------------------------------------------------------------------------
// 销毁自旋锁
int pthread_spinlock_destory(pthread_spinlock_t *spin);
-------------------------------------------------------------------------------------
// 获得自旋锁
int pthread_spinlock_lock(pthread_spinlock_t *spin);
-------------------------------------------------------------------------------------
// 非自旋获得自旋锁
int pthread_spinlock_trylock(pthread_spinlock_t *spin);
-------------------------------------------------------------------------------------
// 释放自旋锁
int pthread_spinlock_unlock(pthread_spinlock_t *spin);
以上函数返回值:成功0,失败设置errno
注:自旋锁和互斥锁类似,唯一的区别就是它是忙等阻塞状态,而互斥锁是通过休眠阻塞,所以自旋锁在等待锁的过程中会消耗大部分CPU时间片,但是可以减少内核的线程间切换作业
线程同步API及它们的属性的更多相关文章
- UNIX环境高级编程——线程同步之条件变量以及属性
条件变量变量也是出自POSIX线程标准,另一种线程同步机制.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量来 ...
- UNIX环境高级编程——线程同步之读写锁以及属性
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...
- 使用Win32 API实现生产者消费者线程同步
使用win32 API创建线程,创建信号量用于线程的同步 创建信号量 语法例如以下 HANDLE semophore; semophore = CreateSemaphore(lpSemaphoreA ...
- [C++] socket - 6 [API互斥事件对象实现线程同步]
/*API互斥事件对象实现线程同步*/ #include<windows.h> #include<stdio.h> DWORD WINAPI myfun1(LPVOID lpP ...
- [C++] socket - 5 [API事件对象实现线程同步]
/*API事件对象实现线程同步*/ #include<windows.h> #include<stdio.h> DWORD WINAPI myfun1(LPVOID lpPar ...
- EventStore .NET API Client在使用线程池线程同步写入Event导致EventStore连接中断的问题研究
最近,在使用EventStore的.NET Client API采用大量线程池线程同步写入Event时(用于模拟ASP.NET服务端大并发写入Event的情况),发现EventStore的连接会随机中 ...
- 线程属性总结 线程的api属性
http://blog.csdn.net/zsf8701/article/details/7842392 //线程属性结构如下:typedef struct{ int etachstate; //线程 ...
- Windows API学习---用户方式中的线程同步
前言 当所有的线程在互相之间不需要进行通信的情况下就能够顺利地运行时, Micrsoft Windows的运行性能最好.但是,线程很少能够在所有的时间都独立地进行操作.通常情况下,要生成一些线程来处理 ...
- C#中的线程(二) 线程同步基础
1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具: 简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...
随机推荐
- Windows下遍历某目录下的文件
需求:要求遍历某个目录下的所有文件,文件夹 之前遇到过一些参考程序,其中有一种方法只能遍历 FAT32 格式的目录, 无法遍历NTFS的目录.
- vs2017搭建linux c++开发环境
最近一直在阅读ovs的源码,看到用户态代码的时候,需要对用户态的代码进行调试,一开始想直接使用linux中的GDB进行调试,但是ovs的工程太过于复杂,从网上找了些文章,发现vs2017能够支持lin ...
- Linux内核学习笔记(1)-- 进程管理概述
一.进程与线程 进程是处于执行期的程序,但是并不仅仅局限于一段可执行程序代码.通常,进程还要包含其他资源,像打开的文件,挂起的信号,内核内部数据,处理器状态,一个或多个具有内存映射的内存地址空间及一个 ...
- NO.1:自学python之路------Hello world、判断、循环
引言 人工智能如今越来越贴近生活,在这里将记录我自学python与tensorflow的过程.编程使用IDE:visual studio 2017,python版本3.6.4,tensorflow版本 ...
- C++进阶训练——停车收费系统设计
一.简介 经过一段时间的c++基础学习,是时候做一个较为全面的.运用c++功能的较复杂的项目练练手了. 运用软件:Visual Studio (VS). 题目:c++停车收费系统设计(某本编程书进 ...
- New Year_2019
新年目标 1. own的项目稳定高效,业务能满足业务方需求,功能质量超出业务方期待.2. 工作中成长,包括项目的需求管理,计划排期,整体的把控能力.3. 对公司的业务了解程度达到更高程度. 个人技能目 ...
- scrum立会报告+燃尽图(第三周第六次)
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2286 项目地址:https://coding.net/u/wuyy694 ...
- 第八次作业psp
psp 进度条 代码累积折线图 博文累积折线图 psp饼状图
- 软工实践-Alpha 冲刺 (9/10)
队名:起床一起肝活队 组长博客:博客链接 作业博客:班级博客本次作业的链接 组员情况 组员1(队长):白晨曦 过去两天完成了哪些任务 描述: 已经解决登录注册等基本功能的界面. 完成非功能的主界面制作 ...
- sql主表分页查询关联子表取任意一条高效方案
有个业务场景,主表中一条数据,在子表中有多条详情数据.对数据进行展示的时候,产品希望随意拿一条子表的数据关联展示出来,用了很多方案,但是都不够好. sql查询取子表任意一条,多个字段的方案 最终找到一 ...