随想录(为什么循环队列具有先天的并行性)
2023-09-27 14:27:11 时间
【声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
循环队列是很多人喜欢用的一种数据结构。本着先来先服务的特性,循环队列是一种十分简单、健壮的数据结构。不像链表、二叉树,如果使用不慎,就会造成很大的麻烦,但是在循环队列上面则没有这个烦恼。
同样而言,循环队列具有很强的并行性,如果服务的数据比较少,那么完全可以利用两个线程进行数据的保存和处理工作。只要注意在编写队列的时候不要引入公共参数,那么几乎不会有任何的并行烦恼。这其中的原因就在于,循环队列没有公共变量,所以不存在对公共变量的修改问题。队列是否为空或者是否为满,完全可以由队列的start和end这两个参数决定,而这两个参数的修改是分开来的,不可能在一个线程上面解决,这就是队列并行的本质原因。
同学们可以自己编写一个简单的双线程代码,验证自己的想法,同时可以不断加深自己对多线程代码的分析和理解能力。下面就是一段在linux上编写的队列处理代码,欢迎大家多提宝贵意见。编译的方法十分简单,即gcc queue.c -g -o queue -lpthread,这里加上-g主要是为了调试使用。
#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <pthread.h>
struct QUEUE
{
int* buffer;
int count;
int start;
int end;
};
#define STATUS int
#define TRUE 1
#define FALSE 0
struct QUEUE* alloc_queue(int count)
{
struct QUEUE* p_queue;
if(0 == count)
{
goto error1;
}
p_queue = (struct QUEUE*)malloc(sizeof(struct QUEUE));
if(NULL == p_queue)
{
goto error1;
}
memset(p_queue, 0, sizeof(struct QUEUE));
p_queue->count = count;
p_queue->buffer = (int*)malloc(sizeof(int)* count);
if(NULL == p_queue->buffer)
{
goto error2;
}
memset(p_queue->buffer, 0, sizeof(int) * count);
return p_queue;
error2:
free(p_queue);
error1:
return NULL;
}
STATUS add_data_into_queue(struct QUEUE* p_queue, int data)
{
if(NULL == p_queue)
{
return FALSE;
}
if(p_queue->end == (p_queue->start + 1) % p_queue->count)
{
return FALSE;
}
p_queue->buffer[p_queue->start] = data;
p_queue->start = (p_queue->start + 1) % p_queue->count;
return TRUE;
}
STATUS get_data_from_queue(struct QUEUE* p_queue, int* p_data)
{
if(NULL == p_queue || NULL == p_data)
{
return FALSE;
}
if(p_queue->start == p_queue->end)
{
return FALSE;
}
p_data[0] = p_queue->buffer[p_queue->end];
p_queue->end = (p_queue->end + 1) % p_queue->count;
return TRUE;
}
static void* set_func(void* args)
{
int index = 1;
if(NULL == args)
{
goto end;
}
while(1)
{
while(FALSE == add_data_into_queue((struct QUEUE*)args, index));
printf("set data %d\n", index ++);
sleep(1);
}
end:
return NULL;
}
static void* get_func(void* args)
{
int data;
if(NULL == args)
{
goto end;
}
while(1)
{
while(FALSE == get_data_from_queue((struct QUEUE*)args, &data));
printf("find data %d\n", data);
sleep(3);
}
end:
return NULL;
}
int main(int argc, char* argv[])
{
pthread_t pid1, pid2;
struct QUEUE* p_queue;
p_queue = alloc_queue(10);
if(NULL == p_queue)
{
goto end;
}
if(pthread_create(&pid1, NULL, set_func, p_queue))
{
goto end;
}
if(pthread_create(&pid2, NULL, get_func, p_queue))
{
goto end;
}
while(1)
{
sleep(0);
}
end:
return 1;
}
相关文章
- 数据结构基础(7) --循环队列的设计与实现
- C/C++数据结构(六) —— 循环队列
- 队列的基本概念详解,循环队列、链式队列的C++详细实现
- Linux网络编程(六)-高并发服务器04:线程池【1个锁(用于锁住队列)、2个条件变量(一个用于阻塞“取任务线程”,一个用于阻塞“任务添加者线程(主线程)”)、1个任务循环队列(用于存放任务)】
- oracle的循环
- Handlebars.js循环中索引(@index)使用技巧(访问父级索引)
- Python 3语法小记(六)条件、循环和assert、pass、del
- Node事件循环之EventEmitter
- 循环数组实现队列的四种方式
- hdu1873(看病要排队)循环队列害死我了
- Linux 之Shell for循环
- 基于数组的循环队列(C++模板实现)
- 循环队列的入队、查询队首元素、出队
- php之foreach循环
- 1008 数组元素循环右移问题
- 循环队列
- 1301. C 循环
- 关于Kotlin循环遍历需要注意索引越界的问题
- Python-循环遍历文件
- AcWing 普通队列与循环队列写法
- javascript的队列,优先队列,循环队列
- 面试必杀技,讲一讲Spring中的循环依赖
- Shell脚本之七 选择、循环结构
- 07*循环语句for和while
- .Net用循环链表解决约瑟夫问题