线程同步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 等待另一个线程 ...
随机推荐
- Fedora 28 UEFI模式安装过程记录
这次的折腾是个意外.不过还是要记录一下. 多次做启动盘,把U盘做坏了.将U盘用量产工具修复以后就能做启动盘了.从官网下了Fedora 28的镜像(与CentOS同属RedHat系,尽量与鸟哥一致),用 ...
- mysql先删除后插入导致死锁
所报的错误为:pymysql.err.OperationalError: (1213, 'Deadlock found when trying to get lock; try restarting ...
- 兰亭集势股价疯涨背后:物流成外贸B2C发展掣肘
21世纪经济报道 汤浔芳 北京报道 核心提示:“兰亭集势涨势喜人,这样的增长是这两三年中概股没有出现过的.”一位负责美股投资的基金合伙人告诉记者,此前,中概股比较低迷,持续大幅度上涨,难得一见. 在唯 ...
- Java反编译插件
一.eclipse->help->Eclipse Marketplace 如下图:搜索JadClipse,install进行下载安装,
- Python20-Day01
简述编译型与解释型语言的区别,且分别列出你知道的哪些语言属于编译型,哪些属于解释 编译型语言是一种以编译器来实现的编程语言,优缺点:执行速度快,调试麻烦 编译型语言:Java,Go,C,C++ 解释性 ...
- redis rdb aof比较
Redis中数据存储模式有2种:cache-only,persistence; cache-only即只做为“缓存”服务,不持久数据,数据在服务终止后将消失,此模式下也将不存在“数据恢复”的手段,是一 ...
- ios framework 使用图片资源
framework 的制作工程见:http://www.cocoachina.com/ios/20141126/10322.html: 遇到问题: 由于自己的framework 要使用图片资源,最后找 ...
- Node.js系列——(2)发起get/post请求
服务器与浏览器的交互主要方式有get/post请求. 下面,我们来看一下node.js发起get/post请求. 1.get 由于get请求的参数在url后面,所以相对比较简单.node.js中的ur ...
- SSH框架配置
--------------------------------applicationContext.xml-------------------------------- <?xml vers ...
- 第200天:js---常用string原型扩展
一.常用string原型扩展 1.在字符串末尾追加字符串 /** 在字符串末尾追加字符串 **/ String.prototype.append = function (str) { return t ...