首页 > 其他分享 >C语言队列操作及其安全问题

C语言队列操作及其安全问题

时间:2024-06-18 16:02:48浏览次数:26  
标签:rwlock 队列 value C语言 queue 安全 mutex pthread

在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.原子操作: 某些编译器或硬件平台提供了原子操作,可以直接在不使用锁的情况下保证操作的原子性。这可以减少锁的开销,但通常只适用于简单的操作。


最后,需要注意,使用这些同步机制时,需要确保正确地初始化和销毁它们,并且在适当的时候获取和释放锁。同时,还需要考虑死锁的可能性,并采取相应的预防措施。
 

 

 

 

 

标签:rwlock,队列,value,C语言,queue,安全,mutex,pthread
From: https://blog.csdn.net/shugenlee/article/details/139771123

相关文章

  • 算法课程笔记——单调栈&单调队列
    算法课程笔记——单调栈&单调队列......
  • 卫士通电科网安安全IpSec网关Ukey开发对接
    官方公开的开发文档,有几个坑,着重说一下踩坑的记录过程。1、通过官方的客户端接口模拟程序获取前端参数:随机数和token2、java程序调用官方sdk,postman请求测试:3、贴出关键的java集成类:importcn.hutool.json.JSONObject;importcn.hutool.json.JSONUtil;importcom.ewa......
  • 了解振弦采集仪在建筑物安全监测中的应用与研究
    了解振弦采集仪在建筑物安全监测中的应用与研究摘要:河北稳控科技振弦采集仪是一种常用的结构物安全监测设备,广泛应用于建筑物、桥梁、塔楼等工程结构的监测。本文将从振弦采集仪的原理、应用案例和研究进展等方面进行详细介绍,以便更好地了解振弦采集仪在建筑物安全监测中的应用与......
  • C语言结构体位域的使用技巧(联合体妙用)
    C语言结构体位域的使用技巧基本概念在C语言中,位域(BitFields)是一种数据结构,它允许程序员访问内存中的单个位。位域通常用于硬件编程,例如嵌入式系统开发,因为它们允许程序员直接访问和控制硬件寄存器的特定位。位域在不同的编译器和平台上可能会有不同的内存对齐和打包行为,......
  • 自学黑客(网络安全)
    前言:想自学网络安全(黑客技术)首先你得了解什么是网络安全!什么是黑客!网络安全可以基于攻击和防御视角来分类,我们经常听到的“红队”、“渗透测试”等就是研究攻击技术,而“蓝队”、“安全运营”、“安全运维”则研究防御技术。无论网络、Web、移动、桌面、云等哪个领域,都有攻......
  • 复习与回顾(C语言)
    学习三阶段:初识——>初阶——>进阶注:蓝色字体皆可跳转一阶:初识1.基本了解C语言的基础知识,对C语言有一个大概的认识2.简单认识每个知识点,后期在初阶和进阶进行详细描述学习内容1.什么是C语言2.第一个C语言程序3.数据类型4.变量、常量5.字符串、转义字符、注释......
  • 网络安全管理是一个系统化的过程,旨在保护网络系统及数据免受未经授权的访问和各类网络
    网络安全管理是一个系统化的过程,旨在保护网络系统及数据免受未经授权的访问和各类网络攻击。其工作原理主要包括以下几个方面:预防措施:通过安全配置管理和需求分析确定潜在的安全威胁,并制定相应的预防策略。这包括对网络设备和软件进行严格的安全配置以及定期更新,确保系统......
  • 问题:如果发送者先运行,而队列是在接收者中定义的,// declare a server-named queue var
    在RabbitMQ中,当你使用交换机(Exchange)和绑定(Binding)时,消息的路由是由交换机类型和绑定键(RoutingKey)来决定的,而不是直接由队列名称来决定的。交换机负责接收生产者发送的消息并根据一定的规则将这些消息路由到一个或多个队列中。问题解释与RabbitMQ的原理发送消息时的行为:发送......
  • 生物实验室如何规范安全地使用加密U盘?
    生物实验室在进行科研工作时,通常涉及大量的敏感数据和核心研发成果。为保护这些数据和成果不被非法获取或泄露,许多生物实验室会考虑进行网络隔离。一般来说,大多数会采用物理隔离的方式,将生物实验室的内部网络与外部网络完全断开。这种方式可以确保内部网络不受外部网络的干扰和威......
  • 多种总部文件下发方式比较,哪一种既相应业务效率又保证安全?
    大型企业在全国甚至全球都会设有分公司、办事处、生产工厂、研发中心等不同形式的分支机构,在日常经营中,存在多种总部文件下发的场景,如将公司战略规划与考核、规章制度、新产品信息及定价策略、业务培训指导材料、客户数据及资料、内部通知,红头文件、合同协议等。总部文件下发包......