【Linux系统编程】32.线程同步、锁的使用、互斥锁管理

news2024/10/7 12:19:29

目录

线程同步

锁的使用

注意事项

pthread_mutex_init

注意

参数mutex

参数attr

返回值

动态初始化

静态初始化

pthread_mutex_destroy

参数mutex

返回值

pthread_mutex_lock

参数mutex

返回值

pthread_mutex_unlock

参数mutex

返回值

pthread_mutex_trylock

参数mutex

返回值

测试代码1

测试结果

线程同步

        线程同步,指一个线程发出某一功能调用时,在没有得到结果之前,该调用不返回。同时其它线程为保证数据一致性,不能调用该功能。

        协调同步,对公共区域数据按序访问。防止数据混乱,产生与时间有关的错误。

锁的使用

        建议锁。对公共数据进行保护。所有线程应该在访问公共数据前先拿锁再访问。但锁本身不具备强制性。

注意事项

  • 尽量保证锁的粒度,越小越好。访问共享数据前,加锁。访问结束,立即解锁。

  • 互斥锁本质是结构体。

pthread_mutex_init

初始化一个互斥锁(互斥量),初值可看作1。

man pthread_mutex_init

注意

 

对于这个没有手册页条目问题,直接安装manpages-posix-dev即可。  

sudo apt-get install manpages-posix-dev

参数mutex

       传出参数,调用时传&mutex。

       restrict关键字:只用于限制指针,告诉编译器,所有修改该指针指向内存中内容的操作,只能通过本指针完成。不能通过除本指针以外的其他变量或指针修改。

参数attr

互斥量属性,是一个传入参数,通常传NULL,选用默认属性(线程间共享)。

返回值

成功:0

失败:错误号

动态初始化

pthread_mutex_t mutex;
pthread_mutex_init(&mutex,NULL);	//动态初始化

静态初始化

pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;	//静态初始化

pthread_mutex_destroy

销毁一个互斥锁。

man pthread_mutex_destroy

参数mutex

传出参数,调用时传&mutex。

返回值

成功:0

失败:错误号

pthread_mutex_lock

加锁。可理解为将mutex--(或 -1),操作后mutex的值为 0。

man pthread_mutex_lock

参数mutex

传出参数,调用时传&mutex。

返回值

成功:0

失败:错误号

pthread_mutex_unlock

解锁。可理解为将mutex++(或+1),操作后mutex的值为1。

man pthread_mutex_unlock

参数mutex

传出参数,调用时传&mutex。

返回值

成功:0

失败:错误号

pthread_mutex_trylock

尝试加锁。

man pthread_mutex_trylock

参数mutex

传出参数,调用时传&mutex。

返回值

成功:0

失败:错误号,同时设置错误EBUSY。

测试代码1

借助互斥锁管理共享数据实现同步。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <string.h>

pthread_mutex_t Suo; //锁
int flag;

void *HuiDiao_HanShu(void *arg)
{
    srand(time(NULL));
    while (1)
    {
        flag = pthread_mutex_lock(&Suo); //加锁
        if (flag != 0)
        {
            printf("加锁错误:%s\n", strerror(flag));
            exit(1);
        }
        printf("你好,");
        sleep(rand() % 3);
        printf("世界。\n");
        flag = pthread_mutex_unlock(&Suo); //解锁
        if (flag != 0)
        {
            printf("解锁错误:%s\n", strerror(flag));
            exit(1);
        }
        sleep(rand() % 3);
    }
    return NULL;
}

int main(int argc, char *argv[])
{
    pthread_t ZiXianCheng_ID; //子线程ID
    void *num = NULL;
    srand(time(NULL));

    flag = pthread_mutex_init(&Suo, NULL); //初始化锁
    if (flag != 0)
    {
        printf("初始化锁错误:%s\n", strerror(flag));
        exit(1);
    }

    flag = pthread_create(&ZiXianCheng_ID, NULL, HuiDiao_HanShu, NULL); //创建子线程
    if (flag != 0)
    {
        printf("创建子线程错误:%s\n", strerror(flag));
        exit(1);
    }

    while (1)
    {
        flag = pthread_mutex_lock(&Suo); //加锁
        if (flag != 0)
        {
            printf("加锁错误:%s\n", strerror(flag));
            exit(1);
        }
        printf("NiHao,");
        sleep(rand() % 3);
        printf("ShiJie。\n");
        flag = pthread_mutex_unlock(&Suo); //解锁
        if (flag != 0)
        {
            printf("解锁错误:%s\n", strerror(flag));
            exit(1);
        }
        sleep(rand() % 3);
    }

    printf("开始回收子线程!\n");
    flag = pthread_join(ZiXianCheng_ID, NULL);
    if (flag != 0)
    {
        printf("回收子线程错误:%s\n", strerror(flag));
        exit(1);
    }
    printf("回收子线程完成!\n");

    flag = pthread_mutex_destroy(&Suo); //销毁锁
    if (flag != 0)
    {
        printf("销毁锁错误:%s\n", strerror(flag));
        exit(1);
    }

    pthread_exit(NULL);

    return 0;
}

测试结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1639883.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JAVA面试之MQ

如何保证消息的可靠传输&#xff1f;如果消息丢了怎么办 数据的丢失问题&#xff0c;可能出现在生产者、MQ、消费者中。 &#xff08;1&#xff09;生产者发送消息时丢失&#xff1a; ①生产者发送消息时连接MQ失败 ②生产者发送消息到达MQ后未找到Exchange(交换机) ③生产者发…

Python | Leetcode Python题解之第64题最小路径和

题目&#xff1a; 题解&#xff1a; class Solution:def minPathSum(self, grid: List[List[int]]) -> int:if not grid or not grid[0]:return 0rows, columns len(grid), len(grid[0])dp [[0] * columns for _ in range(rows)]dp[0][0] grid[0][0]for i in range(1, r…

WPF基础应用

WPF参考原文 MVVM介绍 1.常用布局控件 1.1 布局控件 WPF&#xff08;Windows Presentation Foundation&#xff09;提供了多种布局容器来帮助开发者设计用户界面&#xff0c;以下是一些常用的布局&#xff1a; Grid: Grid是最常用的布局容器之一&#xff0c;它允许你通过定…

计算机网络-408考研

后续更新发布在B站账号&#xff1a;谭同学很nice http://【计算机408备考-什么是计算机网络&#xff0c;有什么特点&#xff1f;】 https://www.bilibili.com/video/BV1qZ421J7As/?share_sourcecopy_web&vd_source58c2a80f8de74ae56281305624c60b13http://【计算机408备考…

【论文阅读笔记】TS2Vec: Towards Universal Representation of Time Series

【论文阅读笔记】TS2Vec: Towards Universal Representation of Time Series 摘要 这段文字介绍了一个名为TS2Vec的通用框架&#xff0c;用于学习时间序列数据的表示&#xff0c;可以在任意语义层次上进行。与现有方法不同&#xff0c;TS2Vec通过对增强的上下文视图进行层次化…

C语言指针进阶_字符指针、指针数组、数组指针、函数指针等的介绍

文章目录 前言一、字符指针二、指针数组三、 数组指针1. 数组名和 & 数组名2. 数组指针3. 数组指针解引用 四、数组指针的使用二维数组的传参说明数组指针使用小测验 五、数组传参和指针传参1. 一维数组传参总结2. 二维数组传参总结3. 一级指针传参4. 二级指针传参 六、函数…

React Context

Context https://juejin.cn/post/7244838033454727227?searchId202404012120436CD549D66BBD6C542177 context 提供了一个无需为每层组件手动添加 props, 就能在组件树间进行数据传递的方法 React 中数据通过 props 属性自上而下(由父及子)进行传递&#xff0c;但此种用法对…

Git使用指北

目录 创建一个Git仓库本地仓库添加文件文件提交到本地仓库缓冲区添加远程仓库地址本地仓库推送到远程仓库创建新的分支拉取代码同步删除缓冲区的文件&#xff0c;远程仓库的文件.gitignore文件 创建一个Git仓库 Git仓库分为远程和本地两种&#xff0c;远程仓库如Githu上创建的…

每天五分钟深度学习框架pytorch:如何创建多维Tensor张量元素?

本文重点 上节课程我们学习了如何创建Tensor标量,我们使用torch.tensor。本节课程我们学习如何创建Tensor向量,我们即可以使用torch.Tensor又可以使用torch.tensor,下面我们看一下二者的共同点和不同点。 Tensor张量 tensor张量是一个多维数组,零维就是一个点(就是上一…

Java零基础入门到精通_Day 9

1.ArrayList 编程的时候如果要存储多个数据&#xff0c;使用长度固定的数组存储格式&#xff0c;不一定满足我们的需求&#xff0c;更适应不了变化的需求&#xff0c;那么&#xff0c;此时该如何选择呢? 集 合 集合类的特点:提供一种存储空间可变的存储模型&#xff0c;存储的…

EMP.DLL是什么东西?游戏提示EMP.DLL文件缺失怎么解决

emp.dll文件是Windows操作系统中的一种动态链接库文件&#xff0c;它被设计为可以被多个程序共享使用的模块化文件。这种设计旨在提高系统效率&#xff0c;减少内存消耗&#xff0c;并简化软件的维护和更新。DLL文件通常包含了一系列相关的函数和变量&#xff0c;这些函数和变量…

C++入门系列-内联函数

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内敛函数的地方展开&#xff0c;这就意味着使用内联函数可以提升程序的运行的效率&#xff0c;减小了调用所需…

微软开源 MS-DOS「GitHub 热点速览」

上周又是被「大模型」霸榜的一周&#xff0c;各种 AI、LLM、ChatGPT、Sora、RAG 的开源项目在 GitHub 上“争相斗艳”。这不 Meta 刚开源 Llama 3 没几天&#xff0c;苹果紧跟着就开源了手机端大模型&#xff1a;CoreNet。 GitHub 地址&#xff1a;github.com/apple/corenet 开…

如何判断自己是不是表演型人格障碍?

表演型人格障碍&#xff0c;也叫寻求注意&#xff0c;寻求关注型人格&#xff0c;癔症型人格&#xff0c;是比较常见的人格障碍类型之一。其核心特征包括有&#xff1a;过分的情绪化&#xff0c;夸张的表现形式&#xff0c;渴望成为别人的关注点&#xff0c;其行为往往是幼稚的…

HDR和WDR有什么区别

HDR指高动态范围成像&#xff0c;与之相对的还有一个概念WDR&#xff08;wide dynamic range&#xff09;宽动态范围成像&#xff0c;从概念上来说二者并无本质区别&#xff0c;为了提高图像的动态范围&#xff0c;解决光照条件不一致时图像过暗或过亮的问题。但它们的原理和应…

QT5带UI的常用控件

目录 新建工程&#xff0c;Qmainwindow带UI UI设计器 常用控件区 Buttons 按钮 containers 容器 控件属性区域 对象监视区 布局工具区 信号与槽区 简单例子1 放置一个按钮控件&#xff0c;改文本为发送&#xff0c;该按键为Button1&#xff1b; 按钮关联信号和…

DRF版本组件源码分析

DRF版本组件源码分析 在restful规范中要去&#xff0c;后端的API中需要体现版本。 3.6.1 GET参数传递版本 from rest_framework.versioning import QueryParameterVersioning单视图应用 多视图应用 # settings.pyREST_FRAMEWORK {"VERSION_PARAM": "versi…

C 深入指针(1)

目录 一、const 1、const修饰变量 2、const修饰指针 2.1 const int* p&#xff08;int const* p&#xff09; 2.2 int* const p 2.3 结论 二、指针运算 1、指针 - 整数 2、指针 - 指针 3、指针的关系运算 三、指针的使用 1、模拟实现 strlen 2、传值调用和传址调用…

读天才与算法:人脑与AI的数学思维笔记16_音乐图灵测试

1. 艾米 1.1. 人工智能作曲家 1.1.1. 分析机可能会生成任意复杂程度、精细程度的科学的音乐作品 1.1.1.1. 阿达洛夫莱斯 1.1.2. 巴赫的作品是大多数作曲家开始学习创作的起点&#xff0c;也是大多数计算机开始学习作曲的起点…

汽车车灯罩通常使用的主要材料包括什么?汽车车灯的灯罩如果破损破裂破洞了要怎么修复?

1.聚碳酸酯&#xff08;PC&#xff09;&#xff1a;PC具有高强度、高韧性和耐冲击性&#xff0c;因此常用于汽车车灯的外罩和透镜部分。它还具有良好的透光性&#xff0c;使得车灯能够有效地发光。 2.丙烯酸酯&#xff08;PMMA&#xff09;&#xff1a;PMMA&#xff0c;也称为…