数据结构【二】:简单阻塞队列BlockingQueue
在POSIX多线程【一】:简单队列simple queue的基础上使用内部互斥锁和条件变量来控制并发以达到线程安全的目的,其主要用于 [生产者-消费者] 队列.
1.BlockingQueue初始化时会确定队列容量(_capacity),如果队列已满(capacity=0),则会阻塞enqueue操作.
2.关闭BlockingQueue(调用queue_free)是一个延迟的操作,它会等待所有元素都dequeue,期间,该队列的一切enqueue操作将无效.
3.此代码未经生产环境检验,仅供学习参考.
BlockingQueue.h
#ifndef CUR_BLOCKINGQUEUE_H
#define CUR_BLOCKINGQUEUE_H
#include <stdlib.h>
#include <pthread.h> struct node{
int value;
struct node * next;
}; typedef struct BlockingQueue_ST{
int capacity,remaining,closed;
struct node * head, *tail;
pthread_mutex_t queue_mutex;
pthread_cond_t cond_not_full;
pthread_cond_t cond_not_empty;
pthread_cond_t cond_empty;
}BlockingQueue; extern BlockingQueue* empty_queue(int _capacity);
extern int queue_free(BlockingQueue *q);
extern int is_empty(const BlockingQueue *q);
extern int is_full(const BlockingQueue *q);
extern int enqueue(struct node *item, BlockingQueue *q);
extern struct node* dequeue(BlockingQueue *q); #endif
BlockingQueue.c
#include "BlockingQueue.h"
#include <stdio.h> BlockingQueue* empty_queue(int _capacity)
{
BlockingQueue *q = malloc(sizeof(BlockingQueue));
q->head = q->tail = NULL;
q->capacity = q->remaining = _capacity;
q->closed = ;
pthread_mutex_init(&q->queue_mutex , NULL);
pthread_cond_init(&q->cond_not_full , NULL);
pthread_cond_init(&q->cond_not_empty , NULL);
pthread_cond_init(&q->cond_empty , NULL);
return q;
} int queue_free(BlockingQueue *q)
{
pthread_mutex_lock(&q->queue_mutex);
printf("close queue...\n");
q->closed = ;
//等待cond_empty
while(!is_empty(q))
{
pthread_cond_wait(&q->cond_empty, &q->queue_mutex);
}
free(q);
pthread_mutex_unlock(&q->queue_mutex);
printf("closed...\n");
} int is_empty(const BlockingQueue *q)
{
return q->capacity == q->remaining;
} int is_full(const BlockingQueue *q)
{
return q->remaining == ;
} int enqueue(struct node *item, BlockingQueue *q)
{ if(q->closed) goto err;
//lock
pthread_mutex_lock(&q->queue_mutex);
//等待cond_not_full
while(is_full(q))
{
pthread_cond_wait(&q->cond_not_full, &q->queue_mutex);
} if(is_empty(q))
{
q->head = q->tail = item;
//通知所有等待cond_not_empty的线程
pthread_cond_broadcast(&q->cond_not_empty);
}
else
{
q->tail->next = item;
q->tail = item;
}
q->remaining--;
//unlock
pthread_mutex_unlock(&q->queue_mutex); return ;
err :
return -;
} struct node* dequeue(BlockingQueue *q)
{ //已经关闭的空队列
if(q->closed && is_empty(q)) goto err;
//lock
pthread_mutex_lock(&q->queue_mutex);
//空队列,等待cond_not_empty
while(!q->closed && is_empty(q))
{
pthread_cond_wait(&q->cond_not_empty, &q->queue_mutex);
}
//take
struct node * temp = q->head;
q->head = q->head->next; //在未关闭队列的情况下,唤醒enqueue等待线程
if(!q->closed && is_full(q))
{
pthread_cond_broadcast(&q->cond_not_full); //TODO 1
}
q->remaining++;
//唤醒关闭队列线程
if(q->closed && is_empty(q))
{
pthread_cond_signal(&q->cond_empty);//TODO 2
} //注意:TODO 1和TODO 2其实是互斥的,不可能同时满足条件
//必须先判断是否激活cond_not_full然后remaining++
//最后再判断是否激活cond_empty
//unlock
pthread_mutex_unlock(&q->queue_mutex);
return temp;
err:
return NULL;
}
测试代码 : main.c
#include<stdio.h>
#include<stdlib.h>
#include "BlockingQueue.h"
extern void* func_put(void* _q); BlockingQueue *q;
pthread_t thread1,thread2;
void main()
{
q = empty_queue();
pthread_create(&thread1,NULL,func_put,(void*)q);
pthread_create(&thread2,NULL,func_put,(void*)q); int i;
for(i=; i<=; i++)
{
struct node * item = (struct node *)malloc(sizeof(struct node));
item->value = i;
item->next = NULL;
enqueue(item,q);
printf("enqueue -> thread : %d, value : %d, remaining : %d\n",pthread_self(),i,q->remaining);
sleep();
}
queue_free(q);
} void* func_put(void* _q)
{
BlockingQueue *q = (BlockingQueue*)_q;
struct node *item;
while((item = dequeue(q)) != NULL)
{
printf("dequeue -> thread : %d, value : %d, remaining : %d\n",pthread_self(), item->value,q->remaining);
free(item);
sleep();
}
}
测试结果 :

数据结构【二】:简单阻塞队列BlockingQueue的更多相关文章
- spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
一: ThreadPoolTaskExecutor是一个spring的线程池技术,查看代码可以看到这样一个字段: private ThreadPoolExecutor threadPoolExecut ...
- Java并发指南11:解读 Java 阻塞队列 BlockingQueue
解读 Java 并发队列 BlockingQueue 转自:https://javadoop.com/post/java-concurrent-queue 最近得空,想写篇文章好好说说 java 线程 ...
- java并发包——阻塞队列BlockingQueue及源码分析
一.摘要 BlockingQueue通常用于一个线程在生产对象,而另外一个线程在消费这些对象的场景,例如在线程池中,当运行的线程数目大于核心的线程数目时候,经常就会把新来的线程对象放到Blocking ...
- Java并发(十八):阻塞队列BlockingQueue
阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...
- Java并发编程-阻塞队列(BlockingQueue)的实现原理
背景:总结JUC下面的阻塞队列的实现,很方便写生产者消费者模式. 常用操作方法 常用的实现类 ArrayBlockingQueue DelayQueue LinkedBlockingQueue Pri ...
- 并发编程-concurrent指南-阻塞队列BlockingQueue
阻塞队列BlockingQueue,java.util.concurrent下的BlockingQueue接口表示一个线程放入和提取实例的队列. 适用场景: BlockingQueue通常用于一个线程 ...
- JUC---01阻塞队列(BlockingQueue)
一.什么是阻塞队列 阻塞队列是一个队列,在数据结构中起的作用如上图:当队列是空的,从队列中获取元素的操作将会被阻塞:当队列是满的,从队列中添加元素的操作将会被阻塞 1.为什么需要BlockingQue ...
- Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例
Java阻塞队列(BlockingQueue)实现 生产者/消费者 示例 本文由 TonySpark 翻译自 Javarevisited.转载请参见文章末尾的要求. Java.util.concurr ...
- 阻塞队列BlockingQueue之ASynchronousQueue
一.SynchronousQueue简介 Java 6的并发编程包中的SynchronousQueue是一个没有数据缓冲的BlockingQueue,生产者线程对其的插入操作put必须等待消费者的移除 ...
随机推荐
- HD1046An Easy Task
Problem Description Ignatius was born in a leap year, so he want to know when he could hold his birt ...
- Android反射出一个类中的其他类对象并调用其对应方法
MainActivity如下: package cn.testreflect; import java.lang.reflect.Field; import java.lang.reflect.Met ...
- POJ 3616 Milking Time (排序+dp)
题目链接:http://poj.org/problem?id=3616 有头牛产奶n小时(n<=1000000),但必须在m个时间段内取奶,给定每个时间段的起始时间和结束时间以及取奶质量 且两次 ...
- 使用java发送邮件sp自动发送邮件方法
注意:将jar包复制到web-info文件夹下lib: activation.jar mail.jar //发送邮箱 public static String sendEmail(String sen ...
- fastcgi 分布式
以lighttpd fastcgi写一下自己对fastcgi分布式的理解. 假设一台机器A上运行lighttpd,在这台主机上只是对请求进行分发. 而在其他多台机器上运行多个fastcgi进程,用来接 ...
- LEARUN 开发框架 /aspnetboilerplate ----上海力软信息技术有限公司
LEARUN 开发框架 ----上海力软信息技术有限公司 http://www.learun.cn/ aspnetboilerplate http://www.aspnetboilerplate ...
- 关于 ServiceStack.Redis 4.0 License
今天更新了框架中的Redis驱动ServiceStack.Redis,最新版本4.0.5.0. 在做简单压力测试时出现异常,提示每小时允许6000个请求. The free-quota limit o ...
- Tun/Tap interface tutorial
Foreword: please note that the code available here is only for demonstration purposes. If you want t ...
- How do I place a group of functions or variables in a specific section?
http://supp.iar.com/Support/?Note=27498 EWARM v5.xx (and newer) The placement of a few functions in ...
- javascript删除数组里的对象
Array.prototype.del = function(value) { //删除数组中指定的元素,返回新数组 function hasValue(array, value) { for(var ...