C语言实现读写锁和try...catch逻辑

1. 读写锁代码实现

代码示例创建了多个读者线程和一个写者线程来访问共享资源(这里是一个文件)。在读者线程中,使用了文件I/O函数打开文件、映射文件到内存,并对文件内容进行了读取。在写者线程中,也使用了文件I/O函数打开文件、映射文件到内存,并对文件内容进行了写入。完整代码如下,简洁易懂。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>// 定义读写锁结构体
typedef struct
{pthread_mutex_t mutex;     // 互斥锁,保护对读写锁的访问pthread_cond_t read_cond;  // 读条件变量,用于同步读操作pthread_cond_t write_cond; // 写条件变量,用于同步写操作int readers;               // 当前读者的数量int writer;                // 当前写者的数量(0或1)
} rwlock_t;// 初始化读写锁
void rwlock_init(rwlock_t *lock)
{lock->readers = 0;lock->writer = 0;pthread_mutex_init(&lock->mutex, NULL);pthread_cond_init(&lock->read_cond, NULL);pthread_cond_init(&lock->write_cond, NULL);
}// 上读锁
void rwlock_read_lock(rwlock_t *lock)
{pthread_mutex_lock(&lock->mutex);while (lock->writer > 0){ // 若有写者存在,等待pthread_cond_wait(&lock->read_cond, &lock->mutex);}lock->readers++; // 读者数量增加pthread_mutex_unlock(&lock->mutex);
}// 解读锁
void rwlock_read_unlock(rwlock_t *lock)
{pthread_mutex_lock(&lock->mutex);lock->readers--; // 读者数量减少if (lock->readers == 0){ // 最后一个读者解锁时唤醒写者pthread_cond_signal(&lock->write_cond);}pthread_mutex_unlock(&lock->mutex);
}// 上写锁
void rwlock_write_lock(rwlock_t *lock)
{pthread_mutex_lock(&lock->mutex);while (lock->readers > 0 || lock->writer > 0){ // 若有读者或写者存在,等待pthread_cond_wait(&lock->write_cond, &lock->mutex);}lock->writer = 1; // 写者存在pthread_mutex_unlock(&lock->mutex);
}// 解写锁
void rwlock_write_unlock(rwlock_t *lock)
{pthread_mutex_lock(&lock->mutex);lock->writer = 0; // 写者不存在if (lock->readers > 0){ // 唤醒所有读者pthread_cond_broadcast(&lock->read_cond);}else{ // 或者唤醒一个写者pthread_cond_signal(&lock->write_cond);}pthread_mutex_unlock(&lock->mutex);
}// 示例使用读写锁的线程函数
void *reader_thread(void *arg)
{rwlock_t *lock = (rwlock_t *)arg;printf("Reader thread start.\n");rwlock_read_lock(lock);printf("Reading data...\n");// 进行读操作int fd = open("./shmem.c", O_RDONLY);if (fd == -1){perror("Error opening file");return EXIT_FAILURE;}unsigned char *addr = (unsigned char *)mmap(NULL, 753, PROT_READ, MAP_SHARED, fd, 0);if (addr == MAP_FAILED){perror("Error mapping file");close(fd);return EXIT_FAILURE;}// Print the content byte by bytefor (int i = 0; i < 753; ++i){printf("%c", addr[i]);}printf("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");if (munmap(addr, 753) == -1){perror("Error unmapping file");close(fd);return EXIT_FAILURE;}close(fd);rwlock_read_unlock(lock);printf("Reader thread end.\n");return NULL;
}void *writer_thread(void *arg)
{rwlock_t *lock = (rwlock_t *)arg;printf("Writer thread start.\n");rwlock_write_lock(lock);printf("Writing data...\n");// 进行写操作int fd = open("./shmem.c", O_RDWR);if (fd == -1){perror("Error opening file");return NULL;}unsigned char *addr = (unsigned char *)mmap(NULL, 753, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);if (addr == MAP_FAILED){perror("Error mapping file");close(fd);return NULL;}// Print the content byte by bytefor (int i = 0; i < 753; i++){addr[i] = 'm';}if (munmap(addr, 753) == -1){perror("Error unmapping file");close(fd);return NULL;}close(fd);rwlock_write_unlock(lock);printf("Writer thread end.\n");return NULL;
}int main()
{pthread_t readers[3];pthread_t writer;rwlock_t lock;rwlock_init(&lock);for (int i = 0; i < 3; i++){pthread_create(&readers[i], NULL, reader_thread, &lock);}pthread_create(&writer, NULL, writer_thread, &lock);for (int i = 0; i < 3; i++){pthread_join(readers[i], NULL);}pthread_join(writer, NULL);return 0;
}

2. try…catch

在C语言中,没有像其他编程语言中的原生支持的try-catch语句。但你可以使用setjmplongjmp函数来实现类似的错误处理机制。

未完待续。。。。。。。。。。。。下面是仅是一种简单的实现示例

下面是一个简单的示例代码,演示了如何使用setjmplongjmp来实现try-catch风格的错误处理:

#include <stdio.h>
#include <setjmp.h>jmp_buf jmp_buffer;void divide(int a, int b)
{if (b == 0){printf("Error: Division by zero\n");longjmp(jmp_buffer, 1);}else{int result = a / b;printf("Result: %d\n", result);}
}int main()
{if (setjmp(jmp_buffer) == 0){// 这里是try块divide(10, 0);divide(20, 5);}else{// 这里是catch块printf("Exception caught\n");}return 0;
}

在上面的示例代码中,setjmp用于设置一个跳转点,并返回0。然后,divide函数被调用,如果除数为0,则会调用longjmp跳转回setjmp所设置的跳转点,并返回非零值。在setjmp之后的代码就相当于try块,如果发生错误,则会在longjmp处跳转到setjmp之后,并执行else块作为catch块来处理异常。

需要注意的是,setjmplongjmp的使用需要非常小心,因为它们会绕过正常的函数调用和返回机制,可能导致资源泄漏或非预期的行为。此外,setjmplongjmp只能用于跳出当前的函数范围,不能跨越多个函数。在实际使用中,请务必谨慎并遵循最佳的错误处理实践。

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

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

相关文章

[蓝桥杯 2013 省 AB] 错误票据

题目背景 某涉密单位下发了某种票据&#xff0c;并要在年终全部收回。 题目描述 每张票据有唯一的 ID 号&#xff0c;全年所有票据的 ID 号是连续的&#xff0c;但 ID 的开始数码是随机选定的。因为工作人员疏忽&#xff0c;在录入 ID 号的时候发生了一处错误&#xff0c;造…

【计算机网络】内容整理

概述 分组交换 分组交换则采用存储转发&#xff08;整个包必须到达路由器&#xff0c;然后才能在下一个链路上传输)技术。 在发送端&#xff0c;先把较长的报文划分成较短的、固定长度的数据段。 电路交换 在端系统间通信会话期间&#xff0c;预留了端系统间沿路径通信所需…

在Docker上配置TensorFlow

在Docker上配置TensorFlow 配置WSL 参考教程&#xff1a;https://blog.csdn.net/m0_63969219/article/details/124632640 在上述教程配置的过程中&#xff0c;可能很难在微软商店下到ubuntu&#xff0c;下面给出另外一种解决方案&#xff1a; 接着上面教程 wsl --set-defaul…

跟着cherno手搓游戏引擎【5】layer(层)、Glad

编写基类层&#xff1a; Layer.h:提供Attach链接、Detach解绑、Update刷新、Event事件、GetName方法 #pragma once #include"YOTO/Core.h" #include"YOTO/Event/Event.h" namespace YOTO {class YOTO_API Layer{public:Layer(const std::string& nam…

KB5034439更新安装失败(0x80070643)的简易解决方法

KB5034439&#xff0c;官方的说明为&#xff1a;适用于 Azure Stack HCI 版本 22H2 和 Windows Server 2022 的 Windows 恢复环境更新&#xff08;2024年1月9日发布&#xff09;。 这个更新与Win10上的KB5034441作用类似&#xff0c;因此也遭遇了相同的安装问题。 服务器在安…

微机原理常考填空总结

hello大家好我是吃个西瓜嘤&#xff0c;这篇节只总结微机原理常考填空题都是干货展示常出现的易错点以及微机原理注意事项。 以下仅代表个人发言 #微机原理 正文开始&#xff1a; 1&#xff0c;区分JZ&#xff0c;JNZ技巧 也就是D70用JZ&#xff1b;D71用JNZ。 JZ;条件ZF1时…

【河海大学论文LaTeX+VSCode全指南】

河海大学论文LaTeXVSCode全指南 前言一、 LaTeX \LaTeX{} LATE​X的安装二、VScode的安装三、VScode的配置四、验证五、优化 前言 LaTeX \LaTeX{} LATE​X在论文写作方面具有传统Word无法比拟的优点&#xff0c;VScode作为一个轻量化的全功能文本编辑器&#xff0c;由于其极强的…

一、QT的前世今

一、Qt是什么 1、Qt 是一个1991年由奇趣科技开发的跨平台C图形用户界面应用程序开发框架。它既可以开发GUI程序&#xff0c;也可用于开发非GUI程序&#xff0c;比如控制台工具和服务。 2、Qt是面向对象的框架&#xff0c;具有面向对象语言的特性&#xff1a;封装、继承、多态。…

短视频抖音文案策划创作运营手册资料大全

【干货资料持续更新&#xff0c;以防走丢】 短视频抖音文案策划创作运营手册资料大全 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 抖音运营资料合集&#xff08;完整资料包含以下内容&#xff09; 目录 制作短视频的四部曲 主题 主题是短视频脚本的基调…

sqlalchemy 中的缓存机制解释

SQLAlchemy 的缓存机制主要涉及两个层面&#xff1a;会话&#xff08;Session&#xff09;缓存和查询缓存。这两种缓存机制对于提升应用性能和数据一致性都非常重要。下面详细解释这两种缓存机制&#xff1a; 1. 会话&#xff08;Session&#xff09;缓存 会话缓存是 SQLAlch…

019、错误处理:不可恢复错误与panic!

鉴于上一篇文章过长&#xff0c;不方便大家阅读和理解&#xff0c;因此关于Rust中的错误处理&#xff0c; 我将分以下3篇来讲。 另外&#xff0c;随着我们学习的不断深入&#xff0c;难度也会越来越大&#xff0c;但不用担心。接下来只需要让自己的脚步慢一些&#xff0c;认真搞…

Python入门知识点分享——(十五)自定义函数

函数是一段事先组织好可重复使用的代码块&#xff0c;用于执行特定的任务。函数可以接受输入参数&#xff0c;并返回一个结果&#xff0c;从而提高应用的模块性和代码的重复利用率。先前我们已经介绍了Python中的内置函数&#xff0c;现在我们要学习创建自定义函数&#xff0c;…

深度学习烦人的基础知识(2)---Nvidia-smi功率低,util高---nvidia_smi参数详解

文章目录 问题现象解释解决方案 磨刀不误砍柴工--nvidia-smi参数解读 问题 如下图所示&#xff0c;GPU功率很低&#xff0c;Util占用率高。这个训练时不正常的&#xff01; 现象解释 Pwr是指GPU运行时耗电情况&#xff0c;如图中GPU满载是300W&#xff0c;目前是86W与GPU2的…

Springboot Jackson 序列化与反序列化配置

可解决在使用默认反序列化Jackson时&#xff0c;LocalDateTime类型的请求参数反序列化失败的问题 import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com…

JavaScript 异步编程解决方案-中篇

天下事有难易乎&#xff1f; 为之&#xff0c;则难者亦易矣&#xff1b;不为&#xff0c; 则易者亦难矣。人之为学有难易乎&#xff1f; 学之&#xff0c;则难者亦易矣&#xff1b;不学&#xff0c;则易者亦难矣。 async 函数 和promise then的规则一样 async function fun() …

SpringMVC(六)RESTful

1.RESTful简介 REST:Representational State Transfer,表现层资源状态转移 (1)资源 资源是一种看待服务器的方式,即,将服务器看作是由很多离散的资源组成。每个资源是服务器上一个可命名的抽象概念。因为资源是一个抽象的概念,所以它不仅仅能代表服务器文件系统中的一个文件…

Apache Answer,最好的开源问答系统

Apache Answer是一款适合任何团队的问答平台软件。无论是社区论坛、帮助中心还是知识管理平台&#xff0c;你可以永远信赖 Answer。 目前该项目在github超过10K星&#xff0c;系统采用go语言开发&#xff0c;安装配置简单&#xff0c;界面清洁易用&#xff0c;且开源免费。项目…

Spring Boot - Application Events 的发布顺序_ApplicationFailedEvent

文章目录 Pre概述Code源码分析 Pre Spring Boot - Application Events 的发布顺序_ApplicationEnvironmentPreparedEvent 概述 Spring Boot 的广播机制是基于观察者模式实现的&#xff0c;它允许在 Spring 应用程序中发布和监听事件。这种机制的主要目的是为了实现解耦&#…

go中常见的错误-以及泛型

https://github.com/teivah/100-go-mistakes#table-of-contents nil Map map记得要make初始化&#xff0c; slice可以不用初始化&#xff01; func main() { //assignment to nil map var course map[string]string //如果不初始化&#xff0c;就会为nilcourse["name&quo…

开源云原生安全的现状

近年来&#xff0c;人们非常重视软件供应链的安全。尤其令人担忧的是开源软件发行版中固有的风险越来越多。这引发了围绕云原生开源安全的大量开发&#xff0c;其形式包括软件物料清单 (SBOM)、旨在验证 OSS 包来源的项目等。 许多组织循环使用大型开源包&#xff0c;但只使用…