线程同步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 等待另一个线程 ...
随机推荐
- 【RL系列】马尔可夫决策过程——Gambler's Problem
Gambler's Problem,即“赌徒问题”,是一个经典的动态编程里值迭代应用的问题. 在一个掷硬币游戏中,赌徒先下注,如果硬币为正面,赌徒赢回双倍,若是反面,则输掉赌注.赌徒给自己定了一个目标 ...
- Nginx连载
一. nginx变量(用户变量.内建变量) 用户变量 又称用户自定义变量 Nginx用户变量的可见范围是整个配置文件,甚至可以跨越不通虚拟主机的server配置,但是变量适用范围是不可以跨越自己的容器 ...
- YQCB冲刺周第二天
YQCB冲刺周第二天 1.实现用户记账的功能 2.实现用户头像的设置 3.实现个人设置的功能 遇到的问题: 记账的分类,数据库存取图片,页面跳转+超链接的使用 团队讨论的照片: ...
- ASP.NET MVC5 学习系列之视图
一.视图约定 当创建一个项目模版时,可以注意到,项目以一种非常具体的方式包含了一个结构化的Views目录.在每一个控制器的View文件夹中,每一个操作方法都有一个同名的视图文件与其对应.(约定大于配置 ...
- Croc Champ 2013 - Round 1 E. Copying Data 线段树
题目链接: http://codeforces.com/problemset/problem/292/E E. Copying Data time limit per test2 secondsmem ...
- C语言的知识与能力的自评
1.我希望将来上班的地方是自己所感兴趣的,正在寻找自己感兴趣的,并且正在普及IT行业的相关知识. 2.我认为学习就是一个自我成长和自我提升以及认识世界的方法,学习的作用是可以不断的提升对这个世界的认识 ...
- lintcode-463-整数排序
463-整数排序 给一组整数,按照升序排序,使用选择排序,冒泡排序,插入排序或者任何 O(n2) 的排序算法. 样例 对于数组 [3, 2, 1, 4, 5], 排序后为:[1, 2, 3, 4, 5 ...
- rabbitmqctl 的常用命令
# 查看服务器的状态 rabbitmqctl status # 查看环境变量 rabbitmqctl environment # 停止rabbitmq的应用 rabbitmqctl stop_ ...
- [mysqld_safe]centos7 mysql 安装与配置
查资料发现是CentOS 7 版本将MySQL数据库软件从默认的程序列表中移除,用mariadb代替了. 有两种解决办法: 安装mariadb [root@a ~]# yum install mar ...
- Java ISO 8601时间格式转换
common-lang包: String pattern = "YYYY-MM-dd'T'HH:mm:ssZZ"; System.out.println(DateFormatUti ...