头文件:<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及它们的属性的更多相关文章

  1. UNIX环境高级编程——线程同步之条件变量以及属性

    条件变量变量也是出自POSIX线程标准,另一种线程同步机制.主要用来等待某个条件的发生.可以用来同步同一进程中的各个线程.当然如果一个条件变量存放在多个进程共享的某个内存区中,那么还可以通过条件变量来 ...

  2. UNIX环境高级编程——线程同步之读写锁以及属性

    读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 互 ...

  3. 使用Win32 API实现生产者消费者线程同步

    使用win32 API创建线程,创建信号量用于线程的同步 创建信号量 语法例如以下 HANDLE semophore; semophore = CreateSemaphore(lpSemaphoreA ...

  4. [C++] socket - 6 [API互斥事件对象实现线程同步]

    /*API互斥事件对象实现线程同步*/ #include<windows.h> #include<stdio.h> DWORD WINAPI myfun1(LPVOID lpP ...

  5. [C++] socket - 5 [API事件对象实现线程同步]

    /*API事件对象实现线程同步*/ #include<windows.h> #include<stdio.h> DWORD WINAPI myfun1(LPVOID lpPar ...

  6. EventStore .NET API Client在使用线程池线程同步写入Event导致EventStore连接中断的问题研究

    最近,在使用EventStore的.NET Client API采用大量线程池线程同步写入Event时(用于模拟ASP.NET服务端大并发写入Event的情况),发现EventStore的连接会随机中 ...

  7. 线程属性总结 线程的api属性

    http://blog.csdn.net/zsf8701/article/details/7842392 //线程属性结构如下:typedef struct{ int etachstate; //线程 ...

  8. Windows API学习---用户方式中的线程同步

    前言 当所有的线程在互相之间不需要进行通信的情况下就能够顺利地运行时, Micrsoft Windows的运行性能最好.但是,线程很少能够在所有的时间都独立地进行操作.通常情况下,要生成一些线程来处理 ...

  9. C#中的线程(二) 线程同步基础

    1.同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具:                       简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程 ...

随机推荐

  1. IncDec序列:差分+贪心

    IncDec序列 题目描述: 给定一个长度为 n 的数列 a1,a2,…,an,每次可以选择一个区间[l,r],使下标在这个区间内的数都加一或者都减一. 求至少需要多少次操作才能使数列中的所有数都一样 ...

  2. Sublime Text 3高效实用快捷键

    2017-11-27 16:18:48 Sublime Text 3 高效实用快捷键 Sublime Text 3 软件及注册码 官网下载链接在这里,有时候会很神奇的上不去,可能是因为被Q了,可能就是 ...

  3. 期中HTML代码及技术博客

      <!DOCTYPE html>   <html lang="en">   <head>   <meta charset="U ...

  4. Java 异常注意事项

    异常的注意事项:   1,子类在覆盖父类方法时,父类的方法如果抛出了异常, 那么子类的方法只能抛出父类的异常或者该异常的子类.   2,如果父类抛出多个异常,那么子类只能抛出父类异常的子集.     ...

  5. 1029 C语言文法翻译(2)

    program à external_declaration | program external_declaration 翻译:<源程序>→ <外部声明> | <源程序 ...

  6. laravel5.6 调用第三方类库

    大概流程: 1. 新建一个目录方类库 2. 配置composer配置文件 3. 在项目中使用终端运行composer  dumpautoload 4. 使用时 方法调用可以new对象后->方法名 ...

  7. ASP.NET前后端分离框架

  8. JDK1.8 之Lambda

    Lambda 理解的了很久才有一点小感觉. 语法 lambda表达式的特点,它的语法如下面. parameter -> expression body 下面是一个lambda表达式的重要特征. ...

  9. IPv4编址及子网划分

    在讨论IP编址之前,我们需要讨论一下主机与路由器连入网络的方法.一台主机通常只有一条链路链接到网络:当主机中的IP想发送一个数据报时,它就在链路上发送,主机与物理链路之间的边界叫做接口(interfa ...

  10. 配置用户通过Telnet登录设备的身份认证(AAA本地认证)

    背景信息 用户通过Telnet登录设备时,设备上必须配置验证方式,否则用户无法成功登录设备.设备支持不认证.密码认证和AAA认证三种用户界面的验证方式,其中AAA认证方式安全性最高. 采用AAA本地认 ...