pthread的互斥量和自旋锁

2023-11-11

一、自旋锁与互斥量的区别

在多处理器环境中,自旋锁最多只能被一个可执行线程持有。如果一个可执行线程试图获得一个被争用(已经被持有的)自旋锁,那么该线程就会一直进行忙等待,自旋,也就是空转,等待锁重新可用。如果锁未被争用,请求锁的执行线程便立刻得到它,继续执行。一个被争用的自旋锁使得请求它的线程在等待锁重新可用时自旋,特别的浪费CPU时间,所以自旋锁不应该被长时间的持有。实际上,这就是自旋锁的设计初衷,在短时间内进行轻量级加锁。


信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因此只能在进程上下文使用而不能在中断上下文使用,因为中断的上下文不允许休眠(trylock可以),因此在中断上下文只能使用自旋锁。


自旋锁保持期间是抢占失效的(内核不允许被抢占) ,而信号量和读写信号量保持期间是可以被抢占的。


自旋锁保护的临界区默认是可以相应中断的,但是如果在中断处理程序中请求相同的自旋锁,那么会发生死锁(内核自旋锁可以关闭中断)。

二、互斥量

互斥量初始化:动态初始化和编译期初始化

int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

动态初始化是通过调用pthread_mutex_init函数实现的,如果是动态初始化为了防止初始化期间竞争,通常使用下面的方式

static pthread_once_t foo_once = PTHREAD_ONCE_INIT;
static pthread_mutex_t foo_mutex;


void foo_init()
{
    pthread_mutex_init(&foo_mutex, NULL);
}


void foo()
{
    pthread_once(&foo_once, foo_init);
    pthread_mutex_lock(&foo_mutex);
   /* Do work. */
    pthread_mutex_unlock(&foo_mutex);
}


互斥量属性

int pthread_attr_init(pthread_attr_t* attr);//初始化线程属性对象
int pthread_attr_destroy(pthread_attr_t * attr);//销毁线程属性对象,被销毁的线程属性对象只有再次初始化之后才能使用
下面的函数用于获取和设置线程属性对象的某个属性
int pthread_mutexattr_init(pthread_mutexattr_t* attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t* attr);
int pthread_mutexattr_getshared(const pthread_mutexattr_t* attr, int* pshared);
int pthread_mutexattr_setshared(pthread_mutexattr_t* attr, int* pshared);
PTHREAD_PROCESS_SHARED:互斥锁可以被跨进程共享
PTHREAD_PROCESS_PRIVATE:只能被初始化线程所属的进程中的线程共享
int pthread_mutexattr_gettype(const pthread_mutexattr_t* attr, int* type);
int pthread_mutexattr_settype(pthread_mutexattr_t* attr, int type);
PTHREAD_MUTEX_NOMAL:
公平锁,对一个已经加锁的普通锁再次加锁,将引发死锁;对一个已经被其他线程加锁的普通锁解锁,或者对一个已经解锁的普通锁再次解锁,将导致不可预期的后果。
PTHREAD_MUTEX_ERRORCHECK:检错锁,对一个已经加锁的检错锁再次加锁,则加锁操作返回EDEADLOCK。对一个已经被其他线程加锁的检错锁解锁,或者对一个已经解锁的检错锁再次解锁,则解锁操作返回EPERM。
PTHREAD_MUTEX_RECURSIVE:嵌套锁,错误使用返回EPERM
PTHREAD_MUTEX_DEFAULT:跟nomal差不多。

互斥量操作

对锁的操作主要包括加锁 pthread_mutex_lock()、解锁pthread_mutex_unlock()和测试加锁 pthread_mutex_trylock()三个。
int pthread_mutex_lock(pthread_mutex_t *mutex)
int pthread_mutex_unlock(pthread_mutex_t *mutex)
int pthread_mutex_trylock(pthread_mutex_t *mutex)
pthread_mutex_trylock()语义与pthread_mutex_lock()类似,不同的是在锁已经被占据时返回EBUSY而不是挂起等待

注意:

1、线程在阻塞等待互斥量的时候可以响应信号,从信号处理函数返回之后会依然阻塞等待信号量,这点与阻塞系统调用不同(返回-1,errno=EINT)。

2、线程在获取互斥量之后可能被取消(pthread_cancel),因此必须配合使用pthread_cleanup_push / pthread_cleanup_pop系统调用释放以获取的互斥量。

三、自旋锁

自旋锁初始化
int pthread_spin_destroy(pthread_spinlock_t *lock);
int pthread_spin_init(pthread_spinlock_t *lock, int pshared);
如果想要使用自旋锁同步多进程,那么设置pshared=PTHREAD_PROCESS_SHARED,然后在进程共享内存中分配pthread_spinlock_t 对象即可(pthread_mutex_t亦如此)。


自旋锁操作

int pthread_spin_lock(pthread_spinlock_t *lock);
int pthread_spin_trylock(pthread_spinlock_t *lock);
int pthread_spin_unlock(pthread_spinlock_t *lock)
;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

pthread的互斥量和自旋锁 的相关文章

随机推荐

  • 2020-11-24-ElasticSearch7.x学习笔记

    笔记记录 B站狂神说Java的ElasticSearch课程 https www bilibili com video BV17a4y1x7zq 在学习ElasticSearch之前 先简单了解一下Lucene Doug Cutting开发
  • 根据PV或者QPS来计算需要多少台机器

    QPS 单个进程每秒请求服务器成功的次数 req sec 总请求数 进程总数 请求时间 一般使用http load进行统计 每台服务器每天的PV QPS x 3600 x 6 或者乘以8小时 一天按照6或者8小时计算 晚上可能没人访问 服务
  • Conda环境 下载Jupyter Lab并使用

    1 下载Jupyter Lab conda 安装方式 conda install jupyterlab conda install c conda forge jupyterlab python 安装方式 pip install jupyt
  • python waitress_python 角度理解web服务器

    概述 web服务器实际上就是一个运行在物理机上的网络服务器 它等待客户端给他发送请求 成功接收后将客户端请求的资源响应给它 客户端与服务端的通信通过http协议实现 客户端可以是浏览器或者可以发送请求的一段程序 一 一个简单的web服务器
  • Android11 热点设置永不关闭

    Android11 热点设置永不关闭 文章目录 Android11 热点设置永不关闭 一 前言 二 framework设置热点永不超时关闭 三 基于 SoftApManager java 研究超时逻辑 三 总结 1 设置热点不关闭的方法 1
  • cutlass入门: 调用cutlass做通用矩阵乘法Gemm(附代码)

    cutlass是CUDA C 模板抽象的集合 用于实现CUDA中所有级别和规模的高性能矩阵乘法 GEMM 和相关计算 相较于cuBLAS和cuDNN cutlass中包含了更多可重用的模块化软件组件 这使得cutlass相较于前两者更为灵活
  • 详细介绍InnoDB数据存储结构

    InnoDB数据存储结构 1 数据库的存储结构 页 索引结构给我们提供了高效的索引方式 不过索引信息以及数据记录都是保存在文件上的 确切说是存储在页结构中 另一方面 索引是在存储引擎中实现的 MySQL服务器上的存储引繁负责对表中数据的读取
  • 接口测试简介以及接口测试用例设计思路

    接口测试简介 1 什么是接口 接口就是内部模块对模块 外部系统对其他服务提供的一种可调用或者连接的能力的标准 就好比usb接口 他是系统向外接提供的一种用于物理数据传输的一个接口 当然仅仅是一个接口是不能进行传输的 我们还的对这个接口怎么进
  • OpenCV读取图像_显示图像和保存图像

    配置好 OpenCV 以后 包含以下两个头文件 include cv h include highgui h IplImage image cvLoadImage D 123 jpg 1 函数cvLoadImage 的第1 个参数是图像文件
  • C++中插件使用举例

    插件并不是在构建时链接的 而是在运行时发现并加载的 因此 用户可以利用你定义好的插件API来编写自己的插件 这样他们就能以指定方式扩展API的功能 插件库是一个动态库 它可以独立于核心API编译 在运行时根据需要显示加载 不过插件也可以使用
  • 左耳朵耗子:拖累开发团队效率的困局与解决之道

    作者 陈皓编辑 小智影响软件开发团队效率的因素有许多 产品和业务上的效率问题固然是根本 但很多时候 这种问题并没有解 如果只从软件开发的过程出发 哪些开发方式是典型 又该怎么解呢 写在前面 我之前写过一篇叫 加班与效率 的文章 从概念上说了
  • outlook中打开链接时收到错误信息

    http helpdesk blog 51cto com 219783 233525 症状 outlook中打开链接时收到错误信息 一般性错误 http 找不到应用程序 原因 IE非默认浏览器 解决方法 打开任意文件夹 工具 文件夹选项 文
  • 【python】—— python的基本介绍并附安装教程

    前言 今天 我将给大家讲解关于python的基本知识 让大家对其有个基本的认识并且附上相应的安装教程以供大家参考 接下来 我们正式进入今天的文章 目录 前言 一 Python 背景知识 二 Python 都能干啥 三 Python的优缺点
  • 判断一个数是否为素数之费马测试

    费马测试被称为概率性素性测试 它判断的是 某个数是素数的概率大不大 如果P为素数 那么所有比P小的数Q都满足公式 QP mod P Q 即 例素数5的性质 比素数5小的数有4 3 2 1 那么 45 45 1024 mod 5 4 35 3
  • 电脑性能,如何提高电脑性能 方法介绍【图文教程】

    在这个信息传播飞速的当下 网络是人们必不可少的传播工具 网络传播信息的途径就是通过电脑 电脑如今已经是每家每户的宠儿了 几乎每个人都有自己的电脑 然而电脑与电脑之间也有差异 它们最大的不同就是性能方面 影响性能的主要因素是硬件 当然还有其它
  • C#学习教程六

    C 异常机制具有如下的特征 1 所有异常必须用System Exception类或者从System Exception派生的类实例来标识 2 可以使用fianlly块编写在正常执行或异常情况下都要执行的终止代码 3 系统级的异常如移除 被零
  • keepalived双主模式(互为主备)

    考虑到keepalived高可用 备节点的机器基本上属于空闲状态 很浪费硬件资源 所以我们可以让keepalived互为主备 跑多个实例 第一个节点配置 vim etc keepalived keepalived conf global d
  • Qt中Udp通信、Udp广播和组播(QT七)

    目录 一 UDP通信 1 Qt中udp通信QUdpSocket 1 发送端 2 接收端 2 Udp通信广播 1 app端UdpApp 2 控制器端UdpControl 3 Udp通信组播 1 组播发送端 2 组播接收端 3 如果要接收组播数
  • 华为服务器bios中修改磁盘格式,华为服务器设置bios

    华为服务器设置bios 内容精选 换一换 通过在BIOS中设置一些高级选项 可以有效提升虚拟化平台性能 表1列出了TaiShan服务器和性能相关的BIOS推荐配置项 开启CPU预取配置选项的目的在于CPU先行提取下一段指令以提高系统效能 在
  • pthread的互斥量和自旋锁

    一 自旋锁与互斥量的区别 在多处理器环境中 自旋锁最多只能被一个可执行线程持有 如果一个可执行线程试图获得一个被争用 已经被持有的 自旋锁 那么该线程就会一直进行忙等待 自旋 也就是空转 等待锁重新可用 如果锁未被争用 请求锁的执行线程便立