pthread_mutex_lock的thread特性

简介:

pthread_mutex_lock的thread特性

作者:gfree.wind@gmail.com
博客:blog.focus-linux.net linuxfocus.blog.chinaunix.net
微博:weibo.com/glinuxer
QQ技术群:4367710

前几天写了一段示例代码,想说明一下可重入函数。所以我在一个函数中使用了pthread_mutex_lock,来说明一旦函数使用了锁,就变成了不可重入的函数。

#include 
#include 

#include 
#include 
#include 
#include 

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

static const char * const caller[2] = {"main", "signal handler"};
static volatile int signal_handler_exit = 0;

static void hold_mutex(int c)
{
        printf("enter hold_mutex [caller %s]\n", caller[c]);

        pthread_mutex_lock(&mutex);

        /* 保证信号函数退出前, main线程始终拥有锁 */
        while (!signal_handler_exit && c != 1) {
                sleep(5);
        }

        pthread_mutex_unlock(&mutex);

        printf("leave hold_mutex [caller %s]\n", caller[c]);
}

static void signal_handler(int signum)
{
        hold_mutex(1);
        signal_handler_exit = 1;
}
int main()
{
        signal(SIGALRM, signal_handler);

        alarm(3);

        hold_mutex(0);

        return 0;
} .h>.h>.h>.h>.h>

上面代码很简单,main函数调用hold_mutex来持有锁。hold_mutex直到SIGALRM信号处理函数返回后,才会释放锁和退出。同时,main利用alarm,在3秒后可以收到信号SIGALRM,而SIGALRM的信号处理函数也会调用hold_mutex。

这就保证了,在main线程持有锁的过程中,通过信号处理机制,再次进入hold_mutex,来造成“死锁”的场景。用以说明hold_mutex是不可重入的。

可是运行结果让我很意外。。。

[fgao@fgao test]#./a.out
enter hold_mutex [caller main]
enter hold_mutex [caller signal handler]
leave hold_mutex [caller signal handler]
leave hold_mutex [caller main]
[fgao@fgao test]# 

这是怎么回事呢?为什么在main拿到锁以后,信号处理函数还是可以拿到锁呢?我决定在这样试一下,直接在hold_mutex中再次拿锁。 代码变成了下面这样:

#include 
#include 

#include 
#include 
#include 
#include 

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

static void hold_mutex(int c)
{
        if (c == 0) {
                return;
        }


        printf("enter hold_mutex [caller %d]\n", c);

        pthread_mutex_lock(&mutex);

        hold_mutex(c-1);

        pthread_mutex_unlock(&mutex);

        printf("leave hold_mutex [caller %d]\n", c);
}

int main()
{
        hold_mutex(3);

        return 0;
} .h>.h>.h>.h>.h>

执行结果如下:

[fgao@fgao test]#./a.out
enter hold_mutex [caller 3]
enter hold_mutex [caller 2]
enter hold_mutex [caller 1]
leave hold_mutex [caller 1]
leave hold_mutex [caller 2]
leave hold_mutex [caller 3]
[fgao@fgao test]# 

看到这样的结果,我首先想到难道pthread_mutex_lock是递归锁?但仔细想了想,又推翻了这个想法。递归锁是一种特殊的锁,不大可能会作为默认行为。

当我盯着pthread_mutex_lock这个名字,pthread这个关键字给我带来了提示。这个锁是否是跟线程相关呢?当该线程拥有了该锁后,可以继续上锁呢?

重读了一遍manual手册,证实了自己的想法。 The mutex object referenced by mutex shall be locked by calling pthreadmutexlock(). If the mutex is already locked, the calling thread shall block until the mutex becomes available. This operation shall return with the mutex object referenced by mutex in the locked state with the calling thread as its owner.

最后一句与我猜测的结果一样。虽然猜中了这个结果,但是我却没有一点兴奋,因为做Linux程序员已经有六、七年了,居然刚发现pthread_mutex_lock的这个特性。

目录
相关文章
|
7月前
|
JSON Java API
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的使用
本文详细介绍了Swagger2的使用方法,包括在Spring Boot项目中的配置与应用。重点讲解了Swagger2中常用的注解,如实体类上的`@ApiModel`和`@ApiModelProperty`,Controller类上的`@Api`、`@ApiOperation`以及参数上的`@ApiParam`等。通过示例代码展示了如何为实体类和接口添加注解,并在页面上生成在线接口文档,实现接口测试。最后总结了Swagger的优势及其在项目开发中的重要性,提供了课程源代码下载链接供学习参考。
421 0
微服务——SpringBoot使用归纳——Spring Boot集成 Swagger2 展现在线接口文档——Swagger2 的使用
|
12月前
|
JavaScript 前端开发 UED
Vue执行流程及渲染解析
【10月更文挑战第5天】
|
12月前
|
Kubernetes Cloud Native API
掌握Dapr:构建可移植的微服务应用
【10月更文挑战第8天】Dapr(Distributed Application Runtime)是一个开放、可移植的运行时环境,旨在简化微服务应用的构建。它通过提供一套API处理服务发现、状态管理、发布/订阅等常见问题,帮助开发者专注于业务逻辑。本文介绍Dapr的基本概念、核心组件、优势及实施步骤,适用于希望构建弹性、可扩展微服务应用的开发者。
|
关系型数据库 MySQL Java
Flink CDC编译问题之增加依赖包失败如何解决
Flink CDC编译指的是将Flink CDC源代码转换成可执行程序的过程,可能会涉及到依赖管理和环境配置等问题;本合集将介绍Flink CDC编译的步骤、常见错误及其解决办法,以确保顺利完成编译过程。
|
运维 Serverless API
函数计算产品使用问题之如何在Python中使用环境变量
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
120 8
|
人工智能 算法 机器人
分享57个游戏Python源代码总有一个是你想要的
分享57个游戏Python源代码总有一个是你想要的
296 0
|
算法 Java API
探索Java并发编程:Fork/Join框架的深度解析
【2月更文挑战第26天】随着多核处理器的普及,并发编程在软件开发中的重要性日益凸显。Java语言提供了多种并发工具,其中Fork/Join框架是处理分而治之问题的一个强大工具。本文将深入探讨Fork/Join框架的设计原理、使用场景及与传统线程池的区别,并通过实例演示如何有效利用该框架提升程序性能。
|
编解码 计算机视觉 Windows
会声会影最新版2023新增功能及配置要求
可能大家已经看到网络上关于会声会影2023新版的一些消息,甚至还有人放出了安装包,这里提醒一下各位粉丝不要心急,今天coco玛奇朵在这里分享2023新版公布信息及下载。会声会影2023中文版功能非常强大的视频编辑软件,非常专业的使用效果,会声会影2023中文版可以针对剪辑电影进行使用,非常强大的色彩校正方式,无论什么光线下进行拍摄,都可以通过后期进行调整,并且里面超多不同的专场设置,能够让你的视频变得更加自然,不会出现非常生硬的专场,强大的编辑器可以下载免费使用。
599 0
|
自然语言处理 Rust 算法
【算法】11. 盛最多水的容器(多语言实现)
给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 说明: 你不能倾斜容器。
【算法】11. 盛最多水的容器(多语言实现)
|
并行计算 PyTorch 算法框架/工具
torch中 x数据已经使用x.to(device), 再使用x.to(device)会报错吗?
在 PyTorch 中,如果已经将一个张量 (tensor) 移到了指定的设备上,再次调用 to 方法将不会产生任何影响,也不会报错。这是因为 to 方法内部会检查当前张量所在的设备和目标设备是否一致,如果一致,则直接返回原始张量。 以下是一个简单的示例代码,演示了当我们尝试将已经被移动到 GPU 上的张量再次移动到相同的 GPU 设备时,不会引发错误:
576 0