day8 互斥锁/读写锁的概念及使用、死锁的避免

news2024/12/28 18:52:31

目录

互斥锁的概念和使用

线程通信 - 互斥

互斥锁的创建和销毁

互斥锁的创建

互斥锁的销毁

互斥锁的使用

申请锁

释放锁


互斥锁的概念和使用

线程通信 - 互斥

临界资源:

一次只允许一个任务(进程、线程)访问的共享资源;

临界区:

访问临界资源的代码;

互斥机制:

mutex互斥锁,任务访问临界资源钱申请锁,访问完后释放锁

互斥锁的创建和销毁

互斥锁的创建

两种方法创建互斥锁:静态方式动态方式

动态方式:

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

成功时返回0 ,失败时返回错误码;

参数:

pthread_mutex_t :定义一个互斥锁;

mutex :指向要初始化的互斥锁对象;

mutexattr :用于指定互斥锁属性,如果为NULL测使用缺省属性。

man函数出现 No manual entry for pthread_mutex_xxx(找不到pthread_mutex_xxx)

解决办法:apt-get install manpages-posix-dev

静态方式:

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

互斥锁的销毁

int pthread mutex destroy(pthread mutex_t *mutex)

在Linux中,互斥锁并不占用任何资源,因此LinuxThreads中的 pthread_mutex_destroy()

除了检查锁状态以外(锁定状态则返回EBUSY)没有其他动作。

互斥锁的使用

申请锁

int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex)

成功时返回0, 失败时返回错误码;

参数:

mutex:指向要初始化的互斥锁对象;

pthread_mutex_lock 如果无法获得锁,任务阻塞;

pthread_mutex_trylock 如果无法获得锁,返回EBUSY而不是挂起等待

释放锁

#include <pthread.h>
int pthread_mutex_unlock(pthread_mutex_t *mutex)

成功时返回 0, 失败时返回错误码;

mutex :指向要初始化的互斥锁对象;

问题:实现多个线程写一个文件,使用互斥锁

代码实现:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;


FILE *fp;
void *func2(void *arg){
    pthread_detach(pthread_self());
    printf("This func2 thread\n");
    
    char str[]="I write func2 line\n";
    char c;
    int i=0;
    while(1){
        pthread_mutex_lock(&mutex);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            usleep(1);
            i++;
        }
        pthread_mutex_unlock(&mutex);
        i=0;
        usleep(1);

    }

    pthread_exit("func2 exit");

}

void *func(void *arg){
    pthread_detach(pthread_self());
    printf("This is func1 thread\n");
    char str[]="You read func1 thread\n";
    char c;
    int i=0;
    while(1){
        pthread_mutex_lock(&mutex);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            i++;
            usleep(1);
        }
        pthread_mutex_unlock(&mutex);
        i=0;
        usleep(1);

    }
    pthread_exit("func1 exit");
}


int main(){
    pthread_t tid,tid2;
    void *retv;
    int i;
    fp = fopen("1.txt","a+");
    if(fp==NULL){
        perror("fopen");
        return 0;
    }


    pthread_create(&tid,NULL,func,NULL);
    pthread_create(&tid2,NULL,func2,NULL);
    while(1){    
        sleep(1);
    } 

}

读写锁的概念和使用

特性

对于写者:写者使用写锁,如果当前 没有读者,也没有其他写者,写者立即获得写锁;否则写者将等待,知道没有读者和其他写者;

对于读者 :读者使用读锁,如果当前没有写者,读者立即获取读锁;否则读者等待,知道没有写者。

注意:

同一时刻只有一个线程可以获得写锁,同一时刻可以有多个线程获得读锁。

读写锁处于写锁状态时,所有试图对读写锁加锁的线程,不管是读者试图加读锁,还是写者试图加写锁,都会被阻塞;

读写锁处于读锁状态时,有写者试图加写锁时,之后的其他线程的读锁请求会被阻塞,以避免写者长时间的不写锁;

读写锁的创建

初始化一个读写锁:

pthread_rwlock_init

读 锁定 读写定:

pthread_rwlock_rdlock

非阻塞 读 锁定:

pthread_rwlock_tryrdlock

写 锁定 读写锁:

pthread_rwlock_wrlock

非阻塞 写 锁定:

pthread_rwlock_trywrlock

解锁 读写锁:

pthread_rwlock_unlock

释放 读写锁

pthread_rwlock_destroy

代码实现:

#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>


pthread_rwlock_t rwlock;

FILE *fp;
void * read_func(void *arg){
    pthread_detach(pthread_self());
    printf("read thread\n");
    char buf[32]={0};
    while(1){
        //rewind(fp);
        pthread_rwlock_rdlock(&rwlock);
        while(fgets(buf,32,fp)!=NULL){
            printf("%d,rd=%s\n",(int)arg,buf);
            usleep(1000);
        }
        pthread_rwlock_unlock(&rwlock);
        sleep(1);
    }

}



void *func2(void *arg){
    pthread_detach(pthread_self());
    printf("This func2 thread\n");
    
    char str[]="I write func2 line\n";
    char c;
    int i=0;
    while(1){
        pthread_rwlock_wrlock(&rwlock);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            usleep(1);
            i++;
        }
        pthread_rwlock_unlock(&rwlock);
        i=0;
        usleep(1);

    }

    pthread_exit("func2 exit");

}

void *func(void *arg){
    pthread_detach(pthread_self());
    printf("This is func1 thread\n");
    char str[]="You read func1 thread\n";
    char c;
    int i=0;
    while(1){
        pthread_rwlock_wrlock(&rwlock);
        while(i<strlen(str))
        {
            c = str[i];
            fputc(c,fp);
            i++;
            usleep(1);
        }
        pthread_rwlock_unlock(&rwlock);
        i=0;
        usleep(1);

    }
    pthread_exit("func1 exit");
}


int main(){
    pthread_t tid1,tid2,tid3,tid4;
    void *retv;
    int i;
    fp = fopen("1.txt","a+");
    if(fp==NULL){
        perror("fopen");
        return 0;
    }
    pthread_rwlock_init(&rwlock,NULL);
    pthread_create(&tid1,NULL,read_func,1);
    pthread_create(&tid2,NULL,read_func,2);
    pthread_create(&tid3,NULL,func,NULL);
    pthread_create(&tid4,NULL,func2,NULL);
    while(1){    
        sleep(1);
    } 

}

死锁

概念:

什么是死锁

 

避免方法:

1、锁越少越好,最好使用一把锁;

2、调整好锁的顺序;

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

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

相关文章

Maven-依赖管理

一. 依赖管理 1. maven-依赖管理-依赖配置 依赖&#xff1a;指当前项目运行所需要的jar包。一个项目中可以引入多个依赖&#xff1a; 例如&#xff1a;在当前工程中&#xff0c;我们需要用到logback来记录日志&#xff0c;此时就可以在maven工程的pom.xml文件中&#xff0c…

Python让ChatGPT全自动改写生成文章教程

ChatGPT是一个在自然语言处理领域非常先进的文本生成模型&#xff0c;它能够产生高质量、连贯的文章。它受到了广泛的关注&#xff0c;因为它可以自动生成大量的文本&#xff0c;从而减轻了人工写作的负担。怎么使用chatgpt批量改写文章&#xff1f;最简单的方式就是找到一家接…

I.MX6U开发板使用OTG烧写系统

1.系统烧写 在实际的产品开发中肯定不可能通过网络来运行&#xff0c;否则没网的时候产品岂不 是就歇菜了。因此我们需要将 uboot、linux kernel、.dtb(设备树)和 rootfs 这四个文件烧写到板子 上的 EMMC、NAND 或 QSPI Flash 等其他存储设备上&#xff0c;这样不管有没有网络我…

SpringCloud 使用sentinel

一、添加依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> 二、配置文件配置地址 spring:cloud:sentinel:transport:dashboard: localhost:8080三…

机器学习:基于逻辑回归对优惠券使用情况预测分析

机器学习&#xff1a;基于逻辑回归对优惠券使用情况预测分析 作者&#xff1a;i阿极 作者简介&#xff1a;Python领域新星作者、多项比赛获奖者&#xff1a;博主个人首页 &#x1f60a;&#x1f60a;&#x1f60a;如果觉得文章不错或能帮助到你学习&#xff0c;可以点赞&#x…

Elasticsearch:集群管理的一些建议

在之前的文章 “Elasticsearch&#xff1a;集群管理” &#xff0c;我们对集群管理做了一些介绍。在今天的文章中&#xff0c;我们接着来聊一下有关配置的方面的问题。这在很大程度上取决于你的用例&#xff0c;是索引还是搜索繁重。 我们将在这里讨论在集群设置方面我们需要关…

中国算力的想象力有多大?|产业特稿

巨头入场和“东数西算”的助推&#xff0c;让中国离这个万亿级算力蓝海更近了一步。 作者|思杭 编辑|皮爷 出品|产业家 2023年初&#xff0c;在青岛、济南、日照等12座城市&#xff0c;一座座崭新的大型数据中心拔地而起。 其中&#xff0c;最引人瞩目的属2月23日&#xff…

文件上传漏洞 --- php邂逅windows通用上传缺陷

目录 后端源码 前端源码 后端代码审计 方式一绕过原理 --- 冒号加特性 验证及结果 方式二绕过原理 --- 数据流 验证及结果 环境需求 php5.2.17IIS环境&#xff0c;可以下载phpstuday2018来满足环境的要求。 后端源码 <?php //U-Mail demo ... if(isset($_POST[sub…

【AI能否取代设计师】「Stable Diffusion」AI绘画黑科技将告诉你答案

上一篇文章&#xff1a;【AI绘画】我以Midjourney为主学习AI绘画效果咋样&#xff1f;_山楂山楂丸的博客-CSDN博客 目录 前言 一、「Stable Diffusion」 是什么 二、「Stable Diffusion」上手演练 三、竟然还有ChatGPT&#xff1f; 四、「Stable Diffusion」作品展示 五、…

爆火的Auto-GPT:实战及运行体验

Auto-GPT可以说是目前AI应用方向最火爆的项目了&#xff0c;自从3月份上线以来&#xff0c;一个月疯狂拦下将近7万star&#xff08;截至本文写稿时69.5k&#xff09;。它的目的是探索诸如GPT-4这样的大语言模型自主完成任务的能力。业界也有一些大佬出来表示这个项目真的很有趣…

pnpm与monorepo架构

本文根据b站up小满zs教程记录 软硬连接介绍 在cmd环境下输入mklink 创建链接需要开启管理员模式 软连接 # mklink 要创建的连接名称 源文件 mklink ruan.js ying.js硬链接 共享一个内存地址。 # mklink 要创建的连接名称 源文件 mklink /H ying.js ying.jspn…

工程项目管理系统源码-简洁+好用+全面-工程项目管理

​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 ​系统定义 工程项目管理企业不直接与该工程项目的总承包企…

STL : 单向链表 Forward_list 与 双向链表 List

目录 Forward_list Member functions List Elements access Modifiers Operations Observes Forward_list #include using namespace std; 单链表&#xff1a;数据的存储位置是分散的、随机的&#xff0c;整个链表的数据的线性关系通过指针来维持&#xff1b; 擅长…

【LeetCode 训练营 3,5】无重复字符的最长子串+最长回文子串

&#x1f48c; 博客内容&#xff1a;LeetCode 训练营 &#x1f600; 作  者&#xff1a;陈大大陈 &#x1f680; 个人简介&#xff1a;一个正在努力学技术的准前端&#xff0c;专注基础和实战分享 &#xff0c;欢迎私信&#xff01; &#x1f496; 欢迎大家&#xff1a;这…

架构重构的技巧

1 代码重构 定义 对软件代码做任何改动以增加可读性或者简化结构而不影响输出结果。 目的 增加可读性、增加可维护性、可扩展性 3 关键点 不影响输出不修正错误不增加新的功能性 代码重构时&#xff0c;发现有个功能实现逻辑不合理&#xff0c;可直接修改吗&#xff1f;…

网络安全-JDBC反序列化漏洞与RCE

目录环境Black Hat Europe 2019漏洞原理攻击手法mysql-connector-java的分析Mysql协议抓包分析Mysql服务器docker启动抓包&&分析Fake Mysql Server搭建Java反序列化工具ysoserial使用fnmsd师傅的MySQL_Fake_Server使用Y4tacker师傅的脚本JDBC代码项目架构代码复现参考环…

Python爬虫之读取数据库中的数据

之前几篇我们一直在研究如何从网站上快速、方便的获取数据&#xff0c;并将获取到的数据存储在数据库中。但是将数据存储在数据中并不是我们的目的&#xff0c;获取和存储数据的目的是为了更好的利用这些数据&#xff0c;利用这些数据的前提首先需要从数据库按一定的格式来读取…

LeetCode——二叉树的非递归遍历

144. 二叉树的前序遍历 给你二叉树的根节点root&#xff0c;返回它节点值的前序遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,2,3] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; 输入&#xff1…

[ 应急响应基础篇 ] 使用 Autoruns 启动项分析工具分析启动项(附Autoruns安装教程)

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

Spring详解简介

1、Spring的简介 Spring的英文翻译为春天&#xff0c;可以说是给Java程序员带来了春天&#xff0c;因为它极大的简化了开发。我得出一个公式&#xff1a;Spring 春天 Java程序员的春天 简化开发。最后的简化开发正是Spring框架带来的最大好处。 Spring是一个开放源代码的设计…