线程同步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 等待另一个线程 ...
随机推荐
- ASP.NET MVC - 启动创建项目,未能加载错误
VS2012以常规方式创建一ASP.NET MVC internet 项目.创建后F5启动项目,遇一错误: 未能加载文件或程序集“MySql.Web.v20, Version=6.9.4.0, Cul ...
- win10 tomcat不能访问问题
问题描述:电脑是Win10系统的,安装了Tomcat后,本机通过80端口能顺利访问.但局域网内的其他机器却无法访问这台电脑的Tomcat服务. 故障分析: 将防火墙关闭后,可以访问,所以问题就出在防火 ...
- Codeforces Round #245 (Div. 1) B. Working out dp
题目链接: http://codeforces.com/contest/429/problem/B B. Working out time limit per test2 secondsmemory ...
- virtual judge 本地部署方案
这是一种将自己的电脑当作服务器来部署一个vj的方法,我也是参考前辈们的做法稍作了改动,如果在服务器上部署的话需要在细节上稍作改动: 一.什么是Virtual Judge? vj的工作原理什么? vj ...
- 树莓派无显示器、无网线,优盘(U盘)启动,远程桌面
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:树莓派无显示器.无网线,优盘(U盘)启动,远程桌面 本文地址:http://techi ...
- LR监控tomcat服务器
采用编写VuGen脚本访问Tomcat的Status页面的方式获取性能数据(利用了关联和lr_user_data_point函数),本质上还是使用tomcat自带的监控页面,只是将监控结果加到LR的a ...
- java 基础 --集合--013
1, contains()方法底层依赖的是equals()方法,而定义的类中没有equal()方法,所以它会使用父类Object中的equals()方法,而Object的equals()方法比较的是地 ...
- java 两个数组合并
需求:两个字符串合并(如果想去重复,参考下一篇--数组去重复及记录重复个数) //方法一 Arrays类 String[] a = {"A","B"," ...
- 第199天:js---扩充内置对象功能总结
一.数组 1.删除数组中指定索引的数据 /** 删除数组中指定索引的数据 **/ Array.prototype.deleteAt = function (index) { if (index < ...
- 【Python】极简单的方式序列化sqlalchemy结果集为JSON
继承 json.JSONEncoder 实现一个针对sqlalchemy返回类型的处理方式. sqlalchemy的返回类型有大都有两种,一种是Model对象,一种是Query集合(只查询部分字段). ...