C语言队列操作及其安全问题
在C语言中,队列是一种常用的数据结构,特别适用于嵌入式开发中的任务调度、缓冲区管理等场景。下面是一个简单的循环队列的模板代码,它使用数组来实现队列,并提供了基本的入队(enqueue)和出队(dequeue)操作。
示例代码如下:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define QUEUE_MAX_SIZE 10 // 定义队列的最大容量
// 队列的结构体定义
typedef struct {
int data[QUEUE_MAX_SIZE]; // 存储队列元素的数组(如果需要动态扩展队列容量,可以考虑使用链表来实现队列)
int front; // 队列头部的索引
int rear; // 队列尾部的索引
} Queue;
// 初始化队列
void queueInit(Queue *q) {
q->front = q->rear = 0;
}
// 判断队列是否为空
bool isQueueEmpty(Queue *q) {
return q->front == q->rear;
}
// 判断队列是否已满
bool isQueueFull(Queue *q) {
return (q->rear + 1) % QUEUE_MAX_SIZE == q->front;
}
// 入队操作
bool enqueue(Queue *q, int value) {
if (isQueueFull(q)) {
return false; // 队列已满,无法入队
}
q->data[q->rear] = value;
q->rear = (q->rear + 1) % QUEUE_MAX_SIZE;
return true;
}
// 出队操作
bool dequeue(Queue *q, int *value) {
if (isQueueEmpty(q)) {
return false; // 队列为空,无法出队
}
*value = q->data[q->front];
q->front = (q->front + 1) % QUEUE_MAX_SIZE;
return true;
}
// 打印队列中的所有元素
void printQueue(Queue *q) {
int i = q->front;
for (int count = 0; count < (q->rear - q->front + QUEUE_MAX_SIZE) % QUEUE_MAX_SIZE; count++) {
printf("%d ", q->data[i]);
i = (i + 1) % QUEUE_MAX_SIZE;
}
printf("\n");
}
// 主函数,演示队列的使用
int main() {
Queue q;
queueInit(&q);
// 入队操作
enqueue(&q, 1);
enqueue(&q, 2);
enqueue(&q, 3);
// 打印队列
printf("Queue after enqueue: ");
printQueue(&q);
// 出队操作
int value;
dequeue(&q, &value);
printf("Dequeued value: %d\n", value);
// 再次打印队列
printf("Queue after dequeue: ");
printQueue(&q);
return 0;
}
这段代码定义了一个队列结构体,包括一个整型数组来存储队列元素,以及两个索引来分别表示队列的头部和尾部。 enqueue 函数用于在队列尾部添加元素, dequeue 函数用于从队列头部移除元素。 isQueueEmpty 和 isQueueFull 函数分别用于检查队列是否为空或满。
但是,这个队列实现是线程不安全的。在多线程环境中使用时,需要添加适当的同步机制来避免竞态条件。
考虑引入同步机制,帮助解决上述队列实现中的不安全问题:
1.互斥锁(Mutex): 互斥锁是一种基本的同步机制,用于保护共享资源不被多个线程同时访问。在队列操作中,可以在入队和出队操作前后使用互斥锁来确保每次只有一个线程可以修改队列。
#include <pthread.h>
pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
bool enqueue(Queue *q, int value) {
pthread_mutex_lock(&queue_mutex);
if (isQueueFull(q)) {
pthread_mutex_unlock(&queue_mutex);
return false;
}
q->data[q->rear] = value;
q->rear = (q->rear + 1) % QUEUE_MAX_SIZE;
pthread_mutex_unlock(&queue_mutex);
return true;
}
bool dequeue(Queue *q, int *value) {
pthread_mutex_lock(&queue_mutex);
if (isQueueEmpty(q)) {
pthread_mutex_unlock(&queue_mutex);
return false;
}
*value = q->data[q->front];
q->front = (q->front + 1) % QUEUE_MAX_SIZE;
pthread_mutex_unlock(&queue_mutex);
return true;
}
2.条件变量(Condition Variable): 条件变量可以与互斥锁一起使用,以实现更高级的同步机制。它们允许线程在某些条件不满足时挂起,直到其他线程发出信号。
#include <pthread.h>
pthread_mutex_t queue_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t queue_not_full = PTHREAD_COND_INITIALIZER;
pthread_cond_t queue_not_empty = PTHREAD_COND_INITIALIZER;
bool enqueue(Queue *q, int value) {
pthread_mutex_lock(&queue_mutex);
while (isQueueFull(q)) {
pthread_cond_wait(&queue_not_full, &queue_mutex); // 等待队列有空间
}
q->data[q->rear] = value;
q->rear = (q->rear + 1) % QUEUE_MAX_SIZE;
pthread_cond_signal(&queue_not_empty); // 通知可能有线程在等待出队
pthread_mutex_unlock(&queue_mutex);
return true;
}
bool dequeue(Queue *q, int *value) {
pthread_mutex_lock(&queue_mutex);
while (isQueueEmpty(q)) {
pthread_cond_wait(&queue_not_empty, &queue_mutex); // 等待队列中有元素
}
*value = q->data[q->front];
q->front = (q->front + 1) % QUEUE_MAX_SIZE;
pthread_cond_signal(&queue_not_full); // 通知可能有线程在等待入队
pthread_mutex_unlock(&queue_mutex);
return true;
}
3.读写锁(Read-Write Lock): 如果队列的读操作远多于写操作,使用读写锁可以提高性能。读写锁允许多个读操作同时进行,但写操作会独占锁。
#include <pthread.h>
pthread_rwlock_t queue_rwlock = PTHREAD_RWLOCK_INITIALIZER;
bool enqueue(Queue *q, int value) {
pthread_rwlock_wrlock(&queue_rwlock);
if (isQueueFull(q)) {
pthread_rwlock_unlock(&queue_rwlock);
return false;
}
// ... 入队操作
pthread_rwlock_unlock(&queue_rwlock);
return true;
}
bool dequeue(Queue *q, int *value) {
pthread_rwlock_wrlock(&queue_rwlock);
if (isQueueEmpty(q)) {
pthread_rwlock_unlock(&queue_rwlock);
return false;
}
// ... 出队操作
pthread_rwlock_unlock(&queue_rwlock);
return true;
}
void printQueue(Queue *q) {
pthread_rwlock_rdlock(&queue_rwlock);
// ... 打印队列操作
pthread_rwlock_unlock(&queue_rwlock);
}
4.原子操作: 某些编译器或硬件平台提供了原子操作,可以直接在不使用锁的情况下保证操作的原子性。这可以减少锁的开销,但通常只适用于简单的操作。
最后,需要注意,使用这些同步机制时,需要确保正确地初始化和销毁它们,并且在适当的时候获取和释放锁。同时,还需要考虑死锁的可能性,并采取相应的预防措施。
相关文章:
C语言队列操作及其安全问题
在C语言中,队列是一种常用的数据结构,特别适用于嵌入式开发中的任务调度、缓冲区管理等场景。下面是一个简单的循环队列的模板代码,它使用数组来实现队列,并提供了基本的入队(enqueue)和出队(de…...
next.js v14 升级全步骤|迁移 pages Router 到 App Router
【概括】本文升级整体按照官网文档指引进行,在迁移 pages Router 前先看了官网的实操视频。 【注意】文章内对 .babel.ts、next.config.js 进行了多次更改,最终配置可见 报错3: Server Error ReferenceError: React is not defined 一、升级 Next.js 版…...
如何在Ubuntu上安装WordPress
如何在Ubuntu上安装WordPress 执行系统更新 apt update && apt upgrade第一步 安装 Apache apt install apache2确认 Apache 安装是否成功. systemctl status apache2安装成功后 打开浏览器输入 http://server-ip-address 第二步 安装 MySQL apt install mariad…...
处理导入Excel文件过大导致Zip bomb detected的问题
处理导入Excel文件过大导致Zip bomb detected的问题 处理导入Excel文件过大导致Zip bomb detected的问题解决方案完整示例代码处理内存溢出问题优化处理大文件的策略 处理导入Excel文件过大导致Zip bomb detected的问题 在Java应用中导入Excel文件时,可能会遇到文件…...
【FFmpeg】AVIOContext结构体
【FFmpeg】AVIOContext结构体 1.AVIOContext结构体的定义 参考: FFMPEG结构体分析:AVIOContext 示例工程: 【FFmpeg】调用ffmpeg库实现264软编 【FFmpeg】调用ffmpeg库实现264软解 【FFmpeg】调用ffmpeg库进行RTMP推流和拉流 【FFmpeg】调用…...
Python控制结构
文章目录 控制结构1. 条件语句1.1 if语句1.2 elif语句1.3 else 语句 2. 循环语句2.1 for循环2.2 while循环 控制循环的语句3.1 break语句3.2 continue语句3.3 else语句与循环配合 控制结构 Python中的控制结构是指管理代码执行流程的语句和机制,包括条件语句、循环…...
OpenCV--图形轮廓
图形轮廓 图像轮廓查找轮廓绘制轮廓计算轮廓的面积和周长多边形逼近与凸包外接矩形 图像轮廓 import cv2 import numpy as np""" 图形轮廓--具有相同颜色或灰度的连续点的曲线 用于图形分析和物体的识别和检测 注意:为了检测的准确性,必…...
MYSQL通过EXPLAIN关键字来分析SQL查询的执行计划,判断是否命中了索引
在MySQL中,你可以通过EXPLAIN关键字来分析SQL查询的执行计划,从而判断是否命中了索引。 准备查询语句: 首先,你需要一个带有WHERE子句的SELECT查询,因为WHERE子句中的条件通常与索引相关联。例如: SELECT …...
clean code-代码整洁之道 阅读笔记(第十二章)
第十二章 系统 12.1 通过选进设计达到整洁目的 Kent Beck关于简单设计的四条规则,对于创建具有良好设计的软件有着莫大的帮助。 据Kent所述,只要遵循以下规则,设计就能变得"简单":运行所有测试;不可重复&…...
FFmpeg YUV编码为H264
使用FFmpeg库把YUV420P文件编码为H264文件,FFmpeg版本为4.4.2-0。 需要yuv测试文件的,可以从我上传的MP4文件中用ffmpeg提取,命令如下: ffmpeg -i <input.mp4> -pix_fmt yuv420p <output.yuv> 代码如下:…...
【C语言】顺序表(上卷)
什么是数据结构? 数据结构是由“数据”和“结构”两词组合而来的。 数据需要管理。数据结构就是计算机存储、组织数据的方式。比如一个班级就是一个结构,管理的就是班级里的学生。如果我们要找三年2班的同学李华,就可以直接去三年2班找而不…...
Luma AI如何注册:文生视频领域的新星
文章目录 Luma AI如何注册:文生视频领域的新星一、Luma 注册方式二、Luma 的效果三、Luma 的优势四、Luma 的功能总结 Luma AI如何注册:文生视频领域的新星 近年来,Luma AI 凭借其在文生视频领域的创新技术,逐渐成为行业的新星。…...
一站式实时数仓Hologres整体能力介绍
讲师:阿里云Hologres PD丁烨 一、产品定位 随着技术的进步,大数据正从规模化转向实时化处理。用户对传统的T1分析已不满足,期望获得更高时效性的计算和分析能力。例如实时大屏,城市大脑的交通监控、风控和实时的个性化推荐&…...
如何在 Windows 上安装 Docker Desktop
如何在 Windows 上安装 Docker Desktop Docker 是一个开放平台,用于开发、部署和运行应用程序。Docker Desktop 是 Docker 在 Windows 和 macOS 上的官方客户端,它使得开发者能够轻松地在本地环境中构建、运行和共享容器化应用程序。本文将详细介绍如何…...
WPF由文本框输入的内容动态渲染下拉框
在做项目过程中,需要扫码枪扫描快递单号或者手动输入快递单号时,自动检索该单号是哪个快递公司的,下拉框中自动带出该单号的快递公司。当输入的快递单号不存在时,将数据库中所有快递公司都带出 效果: 通过输入的快递单…...
RPCMon:一款基于ETW的RPC监控工具
关于RPCMon RPCMon是一款基于事件跟踪的WindowsRPC监控工具,该工具是一款GUI工具,可以帮助广大研究人员通过ETW(Event Tracing for Windows)扫描RPC通信。 RPCMon能够为广大研究人员提供进程之间RPC通信的高级视图,该…...
【odoo】常用的字符转义:“>“,“<“,““,“/“等
概要 字符转义是指在编写代码或处理文本数据时,将特殊字符转换为另一种形式,以便在特定的上下文中正确解析和处理这些字符。 内容 特殊字符描述XML转义表示法&和符号&<小于符号<>大于符号>"双引号"单引号&ap…...
李宏毅深度学习项目——HW1个人笔记
视频链接 PDF链接 googleColab链接 GoogleColab是一个免费的jupyter notebook,可以用上面的gpu资源进行训练 题目 通过前两天的数据,预测第三天某个人感染新冠的概率 范例 导包 # Numerical Operations import math import numpy as np# Reading/Wr…...
3D Gaussian Splatting Windows安装
0.安装C++ 编译器 https://aka.ms/vs/17/release/vs_buildtools.exe 1.下载源码 git clone https://github.com/graphdeco-inria/gaussian-splatting --recursive 2.安装cuda NVIDIA GPU Computing Toolkit CUDA Toolkit Archive | NVIDIA Developer 3.安装COLMAP...
人脸识别——可解释的人脸识别(XFR)人脸识别模型是根据什么来识别个人的
可解释性人脸识别(XFR)? 人脸识别有一个任务叫1:N(识别)。这个任务将一个人的照片与N张注册照片进行比较,找出相似度最高的人。 这项任务用于刑事调查和出入境点。在犯罪调查中,任务从监控摄像…...
仓库管理系统的设计
管理员账户功能包括:系统首页,个人中心,管理员管理,公告管理,物资管理,基础数据管理,用户管理 用户账户功能包括:系统首页,个人中心,公告管理,物…...
最火AI角色扮演流量已达谷歌搜索20%!每秒处理2万推理请求,Transformer作者公开优化秘诀
卡奥斯智能交互引擎是卡奥斯基于海尔近40年工业生产经验积累和卡奥斯7年工业互联网平台建设的最佳实践,基于大语言模型和RAG技术,集合海量工业领域生态资源方优质产品和知识服务,旨在通过智能搜索、连续交互,实时生成个性化的内容…...
MySQL:MySQL分组排序函数rank()、row_number()、dense_rank()与partition by结合使用
一、前言 在 MySQL 中,虽然标准的 SQL 函数 RANK(), ROW_NUMBER(), 和 DENSE_RANK() 是 SQL 标准的一部分,但早期的 MySQL 版本并不直接支持这些窗口函数。然而,从 MySQL 8.0 开始,这些函数被引入以支持窗口函数(也称为…...
opencv c++ 检测图像尺寸大小,标注轮廓
1. 项目背景 本项目旨在开发一个图像处理程序,通过使用计算机视觉技术,能够自动检测图像中物体的尺寸并进行分类。项目利用了开源的计算机视觉库 OpenCV,实现了图像的灰度处理、二值化、轮廓检测、边界框绘制以及尺寸分类等功能。通过这些功…...
Python数据可视化基础:使用Matplotlib绘制图表
Python数据可视化基础:使用Matplotlib绘制图表 数据可视化是数据分析中的重要环节,它可以帮助我们更直观地理解数据。Python作为一门强大的编程语言,提供了多种库来支持数据可视化,其中Matplotlib是最为流行和功能丰富的库之一。…...
Java开发接口设计的原则
在现代软件开发实践中,接口设计扮演着至关重要的角色。它不仅关乎代码的结构和未来的可维护性,还直接影响到软件系统的灵活性和扩展性。本文将通过实例详解几个核心的接口设计原则,帮助开发者更好地编写和管理接口,从而提升软件的…...
[火灾警报系统]yolov5_7.0-pyside6火焰烟雾识别源码
国内每年都会发生大大小小的火灾,造成生命、财产的损失。但是很多火灾如果能够早期发现,并及时提供灭火措施,将会大大较小损失。本套源码采用yolov5-7.0目标检测算法结合pyside6可视化界面源码,当检测到火灾时,能否发出…...
机器学习和深度学习区别
定义和范围: 机器学习:是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。它专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改…...
【功能详解】银河麒麟操作系统“安全启动”是如何发挥作用的?
2023年12月,财政部、工信部发布了7项信息类产品《政府采购需求标准》,为包括操作系统在内多项产品的政府集中采购提供政策支撑。其中,安全、可信作为国产操作系统的基本要求备受关注。 安全体系的构建离不开操作系统本身的硬实力,…...
关于多线程的理解
#系列文章 关于时间复杂度o(1), o(n), o(logn), o(nlogn)的理解 关于HashMap的哈希碰撞、拉链法和key的哈希函数设计 关于JVM内存模型和堆内存模型的理解 关于代理模式的理解 关于Mysql基本概念的理解 关于软件设计模式的理解 关于Redis知识的理解 文章目录 前言一、线程…...
番禺企业网站建设/新平台怎么推广
Laravel 8 附带了很酷的新特性,并对队列系统的一些更改。在本文中,我们将研究这些特性和更改。变化Backoff (回退)已将 retryAfter() 方法和 retryAfter 排队作业,邮件,通知和侦听器的属性重命名为 backoff。php artisan queue&am…...
用什么可以做网站/seo关键词排名工具
java包中提供了很多监控JVM的工具类,作为java程序员必须得掌握常用的几个工具,下面是几个常用的JVM性能监控与故障处理工具的介绍与使用。 1、jstack 该命令用于生成当前时刻虚拟机的线程快照,可以用于定位线程出现长时间停顿的原因ÿ…...
wordpress菠菜插件/推广网
新建一个工程名为“Shapes-Procedural2”,为上篇代码增加描述三角形。修改代码如下: // // main.m // Shapes-Procedural // // Created by cloud on 13-3-7. // Copyright (c) 2013年 cloud. All rights reserved. //#import <Foundation/Founda…...
wordpress手机博客主题/2023年6月份疫情严重吗
文章目录一、Ubuntu软件商店二、apt命令安装三、snap命令安装四、dpkg命令安装deb包五、源码安装一、Ubuntu软件商店 我们可以直接打开Ubuntu自带的软件商店,进行搜索下载安装。 对于后缀为deb的安装包,我们也可以在图形界面双击打开,会自动…...
国外做ic的网站/太原seo网站排名
为什么80%的码农都做不了架构师?>>> 一、什么是VLAN VLAN(Virtual LAN),翻译成中文是“虚拟局域网”。LAN可以是由少数几台家用计算机构成的网络,也可以是数以百计的计算机构成的企业网络。VLAN所指的LAN特指使用路由器分割的网络…...
建站之星网站 seo优化/优秀网站设计网站
1、Oracle_Base表示Oracle目录树的根,如F:\oracle\prod t\10.1.0。2、Oracle_Home表示根目录下的主目录,位于Oracle_Base之下,如F:\oracle\prod t\10.1.0\db_1,“\db_1”就是Oracle_Home表示的值,即主目录。它包含与Or…...