多线程互斥锁 pthread_mutex 的使用及初始化问题

2023-11-07

一、互斥锁pthread_mutex的使用

1、初始化锁

        有两种方法初始化互斥锁,静态方式和动态方式。

静态方式:

pthread_mutex_t mutex_lock=PTHREAD_MUTEX_INITIALIZER;

在LinuxThreads实现中,pthread_mutex_t是一个结构,而PTHREAD_MUTEX_INITIALIZER则是一个结构常量的宏。

动态方式:

int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr) 

其中mutexattr用于指定互斥锁属性如下,如果为NULL则使用缺省属性。

        PTHREAD_MUTEX_TIMED_NP,这是缺省值,也就是普通锁。当一个线程加锁以后,其余请求锁的线程将形成一个等待队列,并在解锁后按优先级获得锁。这种锁策略保证了资源分配的公平性。

        PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次unlock解锁。如果是不同线程请求,则在加锁线程解锁时重新竞争。 

        PTHREAD_MUTEX_ERRORCHECK_NP,检错锁,如果同一个线程请求同一个锁,则返回EDEADLK,否则与PTHREAD_MUTEX_TIMED_NP类型动作相同。这样就保证当不允许多次加锁时不会出现最简单情况下的死锁。

        PTHREAD_MUTEX_ADAPTIVE_NP,适应锁,动作最简单的锁类型,仅等待解锁后重新竞争。

2、锁的使用

int pthread_mutex_lock(pthread_mutex_t *mutex)  //加锁,获取不到锁会挂起

int pthread_mutex_unlock(pthread_mutex_t *mutex)  //解锁

int pthread_mutex_trylock(pthread_mutex_t *mutex) //在锁已经被占据时返回EBUSY而不是挂起等待。

int pthread_mutex_destroy(pthread_mutex_t *mutex) //销毁一个互斥锁即意味着释放它所占用的资源,且要求锁当前处于开放状态。由于在Linux中,互斥锁并不占用任何资源,因此LinuxThreads中的 pthread_mutex_destroy()除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。*/

3、代码示例

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
 
void *function(void *arg);
pthread_mutex_t mutex;
int counter = 0;
int main(int argc, char *argv[])
{
    int rc1,rc2;
     
    char *str1="wenhaoll";
    char *str2="linglong";
    pthread_t thread1,thread2;
 
    pthread_mutex_init(&mutex,NULL);
    if((rc1 = pthread_create(&thread1,NULL,function,str1)))
    {
        fprintf(stdout,"thread 1 create failed: %d\n",rc1);
    }
 
    if(rc2=pthread_create(&thread2,NULL,function,str2))
    {
        fprintf(stdout,"thread 2 create failed: %d\n",rc2);
    }
 
    pthread_join(thread1,NULL);
    pthread_join(thread2,NULL);
    return 0;
}
 可以尝试将关于锁的操作去掉,有什么效果
void *function(void *arg)
{
    char *m;
    m = (char *)arg;
    pthread_mutex_lock(&mutex);
    while(*m != '\0')
    {
        printf("%c",*m);
        fflush(stdout);
        m++;
        sleep(1);
    }
    printf("\n");
    pthread_mutex_unlock(&mutex);
}

二、调试遇到的初始化问题

问题描述,在锁初始化时,看到很多应用没有初始化,直接使用,如下示例

pthread_mutex_t log_lock;
 
 
void write1()
{
	char buf[]="111111111111111111111111111111111\n";
	int num=0;
	while(1)
		{
		    pthread_mutex_lock(&log_lock);
 
			//fwrite(buf,sizeof(buf),1,write_fd);
			fprintf(write_fd, buf);
			//write(write_fd,buf,strlen(buf));
			if(++num>=10000)
				{
				printf("1 ok\n");
				pthread_mutex_unlock(&log_lock);
				return;
			}
 
		    pthread_mutex_unlock(&log_lock);
		    usleep(10);
	}
}
int main()
{
    pthread_t write1_id;
	//write_fd = open("./testwrite",O_WRONLY | O_APPEND);
	write_fd = fopen("./testwrite","a+");
	if(write_fd<0)
	 {
	  perror("open");
	  exit(1);
	 }
	//pthread_mutex_init(&log_lock,NULL);
 
	pthread_create(&write1_id,NULL,write1,NULL);
	while(1)
		{
		sleep(1);
	}
		
	return 0;
}

说好的使用前先初始化,但是没有初始化锁也可以正常使用,why?

于是我尝试用gdb跟了一下,我发现这三种方式

  • pthread_mutex_t log_lock; //直接使用
  • pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER;
  • pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

打印出来的pthread_mutex_t结构信息都是一模一样的都是如下:

(gdb) p log_lock
$1 = {__data = {__lock = 0, __count = 0, __owner = 0, __kind = 0, __nusers = 0, {__spins = 0, __list = {__next = 0x0}}}, 
  __size = '\000' <repeats 23 times>, __align = 0}

所以是不是可以说不初始化也可以正常使用锁,如果不初始化使用锁,会有什么样的影响么?

我们来分析一下为什么会这样,然后给出使用建议。

pthread_mutex_t log_lock; //直接使用,

    由于是全局变量,编译后结构体成员默认值为0

pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER;

    这个宏实际定义为

    # define PTHREAD_MUTEX_INITIALIZER  { { 0, 0, 0, 0, 0, 0, { 0, 0 } } } 

pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);

    这个初始化函数没有仔细追代码,猜想也是初始化成员为0

最后建议使用锁时尽量初始化,按照标准流程来。

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

多线程互斥锁 pthread_mutex 的使用及初始化问题 的相关文章

  • ioctl 命令的用户权限检查

    我正在实现 char 驱动程序 Linux 并且我的驱动程序中有某些 IOCTL 命令仅需要由 ADMIN 执行 我的问题是如何在 ioctl 命令实现下检查用户权限并限制非特权用户访问 IOCTL 您可以使用bool capable in
  • 在内核代码中查找函数的最佳方法[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我开始浏览内核代码 遇到的一件事是如何跟踪函数调用 结构定义等 有没有一种好的方法可以快速跳转到函数定义并退出 我尝试过 Source N
  • 找不到包“gdk-pixbuf-2.0”

    我正在尝试在 Amazon Linux 发行版实例上构建 librsvg 我已经通过 yum 安装了大部分依赖项 其中一些在实例上启用的默认 yum 存储库中不可用 因此必须从头开始构建它们 我已经走了很远 但还停留在最后一点 跑步时sud
  • 为什么 Linux 原始套接字的 RX 环大小限制为 4GB?

    背景 我试图mmap 我的原始套接字的 RX 环形缓冲区64 bitLinux 应用程序 我的环由 4096 个块组成 每个块大小为 1MB 总共 4GB 请注意 每个 1MB 块中可以有许多帧 如果您好奇 请参阅此文档了解背景信息 htt
  • SSH,运行进程然后忽略输出

    我有一个命令可以使用 SSH 并在 SSH 后运行脚本 该脚本运行一个二进制文件 脚本完成后 我可以输入任意键 本地终端将恢复到正常状态 但是 由于该进程仍在我通过 SSH 连接的计算机中运行 因此任何时候它都会登录到stdout我在本地终
  • 适用于 Linux 的轻量级 IDE [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 C 中使用单个消息队列是否可以实现双向通信

    我希望服务器向客户端发送一些消息 并让客户端确认它 我被分配了这个任务 我可以在 C linux 中使用单个消息队列来完成它还是我需要创建两个 谢谢 是的 可以使用 sysV 消息队列来做到这一点 从您之前的问题来看 您正在使用该队列 您可
  • tcpdump 是否受 iptables 过滤影响?

    如果我的开发机器有iptables规则到FORWARD一些数据包 这些数据包是否被 tcpdump 捕获 我有这个问题 因为我知道存在其他链称为INPUT如果数据包路由到 它会过滤发往应用程序的数据包FORWARD链 它会到达吗tcpdum
  • 如何在 Ubuntu 中创建公共 HTML 文件夹?

    简单的问题 但由于某种原因我无法在谷歌上找到确切的答案 我在 Slicehost 上安装了全新的 Ubuntu 并且想在我的主目录中为包含一堆静态 HTML 文件的简单网站创建一个公共目录 我该怎么做呢 只是打字的问题吗mkdir publ
  • 执行“minikube start”命令时出现问题

    malik malik minikube start minikube v1 12 0 on Ubuntu 18 04 Using the docker driver based on existing profile Starting c
  • 无需超级用户即可在 Linux 中打开 RAW 套接字

    我必须编写一个在 Linux 上运行的 ping 函数 语言是 C 所以 C 也可以 在网上搜索并查看源代码ping命令 事实证明我应该创建一个原始套接字 icmp sock socket AF INET SOCK RAW IPPROTO
  • C 语言的符号表

    我目前正在开发一种执行模式匹配的静态分析工具 我在用Flex https github com westes flex生成词法分析器 我编写了代码来管理符号表 我不太有经验C 所以我决定将符号表实现为线性链表 include
  • 使用循环在 C 中管道传输两个或多个 shell 命令

    我正在尝试执行ls wc l通过 C 语言程序 而不是使用命令行 这是我当前的工作代码 int main int pfds 2 pipe pfds pid t pid fork if pid 0 The child process clos
  • CMake 链接 glfw3 lib 错误

    我正在使用 CLion 并且正在使用 glfw3 库编写一个程序 http www glfw org docs latest http www glfw org docs latest 我安装并正确执行了库中的所有操作 我有 a 和 h 文
  • 使用 shell 脚本将行附加到 /etc/hosts 文件

    我有一个新的 Ubuntu 12 04 VPS 我正在尝试编写一个安装脚本来完成整个 LAMP 安装 我遇到问题的地方是在 etc hosts文件 我当前的主机文件如下所示 127 0 0 1 localhost Venus The fol
  • 如何使用waf构建共享库?

    我想使用构建一个共享库waf http code google com p waf 因为它看起来比 GNU 自动工具更容易 更简洁 到目前为止 我实际上有几个与我开始编写的 wscript 有关的问题 VERSION 0 0 1 APPNA
  • 内核的panic()函数是否完全冻结所有其他进程?

    我想确认内核的panic 功能和其他类似kernel halt and machine halt 一旦触发 保证机器完全冻结 那么 所有的内核和用户进程都被冻结了吗 是panic 可以被调度程序中断吗 中断处理程序仍然可以执行吗 用例 如果
  • Intel 上的 gcc 中的 _mm_pause 用法

    我参考过这个网页 https software intel com en us articles benefitting power and performance sleep loops https software intel com
  • 绕过 dev/urandom|random 进行测试

    我想编写一个功能测试用例 用已知的随机数值来测试程序 我已经在单元测试期间用模拟对其进行了测试 但我也希望用于功能测试 当然不是全部 最简单的方法是什么 dev urandom仅覆盖一个进程 有没有办法做类似的事情chroot对于单个文件并
  • Linux 为一组进程保留一个处理器(动态)

    有没有办法将处理器排除在正常调度之外 也就是说 使用sched setaffinity我可以指示线程应该在哪个处理器上运行 但我正在寻找相反的情况 也就是说 我想从正常调度中排除给定的处理器 以便只有已明确调度的进程才能在那里运行 我还知道

随机推荐

  • ssm框架整合(项目步骤)

    目录 一 前言 二 SSM框架 2 1 SSM整合到底整合什么 2 2 为什么要整合到一起 2 3 由谁来整合 2 4 ResponseBody注解的作用是什么 2 5 JSON 三 各框架应用场景 3 1 SpringMVC框架 3 2
  • 建立单链表并交换表中任意两个元素

    功能 建立单链表并交换表中任意两个元素 time 2017年3月12日15 07 25 include
  • 2021年 IEEE VIS 科学可视化与体渲染论文整理与分析

    因为最近工作的关系 需要研究一下IEEE VIS中2017年以后的与我之前主要方向 体渲染 医学可视化 有关的论文 我把这些年全部的论文进行了筛选和梳理 总共筛选出57篇论文 打算写一个文章来记录这些内容 这个栏目是2021年的九篇论文的介
  • MNIST数据库介绍及转换

    MNIST数据库介绍 MNIST是一个手写数字数据库 它有60000个训练样本集和10000个测试样本集 它是NIST数据库的一个子集 MNIST数据库官方网址为 http yann lecun com exdb mnist 也可以在win
  • springMVC ResponseBody 返回汉字乱码解决方案

    本文查考借鉴 http blog yimik com archives 899 js里通过ajax调用springmvc 后台返回的中文字符串乱码 通过搜索找解决方 大都让配置StringHttpMessageConverter这个bean
  • 本地JAR打镜像,并启动

    1 准备好jar 和Dockerfile文件 2 使用命令打镜像 docker build t wstest 3 查看镜像 4 由于服务是两个端口 使用以下命令 5 优化怎么随着docker的开启而启动 docker run restart
  • Maltrail恶意流量检测系统

    Maltrail恶意流量检测系统 项目介绍 项目GitHub地址 项目架构 项目数据集 运行方式 订阅源扩展 数据采集模块提取 项目介绍 maltrail是一款轻量级的恶意流量检测系统 其工作原理是通过采集网络中各个开源黑样本 包括IP 域
  • python操作sql

    from pymysql import connect def main 创建connection连接 conn connect host localhost port 3306 user root password 123456 data
  • 深入浅出UML类图(一)

    在UML 2 0的13种图形中 类图是使用频率最高的UML图之一 Martin Fowler在其著作 UML Distilled A Brief Guide to the Standard Object Modeling Language
  • Redis中key-value实现

    实现字典的方法有很多种 最简单的就是使用链表或数组 但是这种方式只适用于元素个数不多的情况下 要兼顾高效和简单性 可以使用哈希表 如果追求更为稳定的性能特征 并且希望高效地实现排序操作的话 则可以使用更为复杂的平衡树 在众多可能的实现中 R
  • JAVA8新特性--集合遍历之forEach

    java中的集合有两种形式Collection
  • 5.2 activiti任务监听器TaskListener

    1 任务监听器定义 任务监听器用于在特定的任务相关事件发生时 执行自定义的Java逻辑或表达式 2 监听器监听的事件 String EVENTNAME CREATE create 创建 当任务已经创建 并且所有任务参数都已经设置时触发 St
  • Basic Level 1090 危险品装箱 (25分)

    题目 集装箱运输货物时 我们必须特别小心 不能把不相容的货物装在一只箱子里 比如氧化剂绝对不能跟易燃液体同箱 否则很容易造成爆炸 本题给定一张不相容物品的清单 需要你检查每一张集装箱货品清单 判断它们是否能装在同一只箱子里 输入格式 输入第
  • Linux期末复习总结

    目录 Linux 系统的结构 shell Linux用户类型及其用户主目录 shell提示符 输入输出重定向 标准输入 输出设备 Linux文件的类型 Linux 的目录结构 基本操作命令 链接命令 ln 链接的特点 tar命令举例 vi
  • 求一批整数中出现最多的各位数字

    描述 给定一批整数 分析每个整数的每一位数字 求出现次数最多的各 位数字 例如给定3个整数1234 2345 3456 其中出现最多次数的数字是3和4 均出现了3次 输入 输入在第1行中给出正整数N 1000 在第二行中给出N个不超过整型范
  • QT QLinearGradient (颜色渐变---应用控件背景渐变)

    示例 frame gt setStyleSheet background color qlineargradient spread pad x1 0 y1 0 x2 1 y2 0 stop 0 030303 stop 0 5 030303
  • 多线程及多进程的选择

    我的理解是进程是指在系统中正在运行的一个应用程序 程序一旦运行就是进程 或者更专业化来说 进程是指程序执行时的一个实例 线程是进程的一个实体 进程 资源分配的最小单位 线程 程序执行的最小单位 线程进程的区别体现在几个方面 0 因为进程拥有
  • 【手撕代码系列】JS手写实现bind方法

    公众号 Code程序人生 分享前端所见所闻 在JavaScript中 bind方法允许我们绑定函数的上下文并返回一个新的函数 在这篇文章中 我们将手写实现bind方法 以更好地了解它的内部工作原理 bind方法的语法 bind方法的语法如下
  • 整数转化为罗马数字

    1 问题描述 罗马数字包含以下七种字符 I V X L C D 和 M 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如 罗马数字 2 写做 II 即为两个并列的 1 12 写做 XII 即为 X
  • 多线程互斥锁 pthread_mutex 的使用及初始化问题

    一 互斥锁pthread mutex的使用 1 初始化锁 有两种方法初始化互斥锁 静态方式和动态方式 静态方式 pthread mutex t mutex lock PTHREAD MUTEX INITIALIZER 在LinuxThrea