Tag/
共719个网摘 [
1 2 3 4 5 6 7 8 ...
24 ]
上一页 |
下一页 |
insulted收录,使用标签:算法,时间:2008-8-27 11:00:11 | 相关网摘,我也收藏
问题描述:Write a program that will accept a fraction of the form N/D, where N is the numerator and D is the denominator and print the decimal representation. If the decimal representation has a repeating sequence of digits, indicate the sequence by enclosing it in brackets. For example, 1/3 = .33333333...is denoted as 0.(3), and 41/333 = 0.123123123...is denoted as 0.(123). Use xxx.0 to denote an integer. Typical conversions are:
1/3 = 0.(3)
22/5 = 4.4
1/7 = 0.(142857)
2/2 = 1.0
3/8 = 0.375
45/56 = 0.803(571428)
Input
A single line with two space separated integers, N and D, 1 <= N,D <= 100000.
Output
The decimal expansion, as detailed above. If the expansion exceeds 76 characters in length, print it on multiple lines with 76 characters per line.
例子:
输入:45 56
输出:0.803(571428)
http://topic.csdn.net/u/20080826/12/ac2fcb2c-bc63-4317-90fe-c6b18f3b9397.html?seed=837861545
perfectpdl收录,使用标签:算法, 生产者消费者,时间:2008-8-25 12:28:21 | 相关网摘,我也收藏
生产者-消费者模型的解决思路——自建队列收藏
新一篇: 用JScript实现MembersTable | 旧一篇: 在Web上用style实现完美颜色渐变
笔者曾遇到这样的需求:某软件在运行中随时有可能向外发送短信,一方面发送短信的设备是个独占资源,另一方面有多个线程要发短信。按照“把不稳定因素限定在一个实体中”的原则,自然就用一个专门的线程来操作短信设备,它的任务是从消息队列中取出要发送的短信,通过短信设备发送出去。
这是比较常见的生产者-消费者模型,即一个模块产生数据,另外模块取得数据并进行处理。如何实现互斥?如何让生产者和消费者都能够方便的工作?
类似这样的情况在编程中十分常见,采用消息队列是很好的解决办法。本文给出的消息队列具有以下特色:
·消息的大小、结构是自由的,甚至可以是一个对象;
·消息队列的长度(容纳消息的个数)是可设定的,超过最大长度可以选择丢弃或等待;
·新消息一般是放在队列的最后面,也可以放在最前面;
·代码少,思路简洁,你可以根据情况扩展;
【设计思路】
设计思路其实很简单,消息队列类CHMQ是个模板类,用CList保存消息,用CriticalSection来实现互斥,用Event来控制消息队列为空或已满的情况。提供以下几个常用接口:
·Push() 在队列尾增加消息,如果消息队列已满,根据设定或丢弃消息,或阻塞直到队列不为满的时候。
·Insert() 在对列头增加消息,其他同Push()。
·Pop() 从队列头中取消息,如果队列为空则阻塞,直到不为空的时候。
·SetMaxCount() 设置消息队列的最大长度,以及如果消息队列满的时候新消息的处理方式。 或丢弃消息,或阻塞直到队列不为满的时候。
·GetMaxCount() 返回消息队列的最大长度,如果没有设置最大长度则返回-1。
·GetQueueCount() 返回目前消息队列中的消息个数。
【扩展】
(1) 目前一个CHMQ对象仅支持一个消息队列,可以扩展成多个消息队列
(2) 消息队列为空时,Pop()一直阻塞到有新消息时才返回,可以扩展成超时返回
(3) 消息队列已满时,Push()和Insert()可能会阻塞到队列不满的时候,可以扩展成超时丢弃
#ifndef CHMQ_H
#define CHMQ_H
#include
#include
template
class CHMQ
{
public:
CHMQ()
{
m_nMax = -1;
m_bDrop = FALSE;
::InitializeCriticalSection(&m_lock);
m_hPushEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT(m_hPushEvent != NULL);
m_hPopEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT(m_hPopEvent != NULL);
}
~CHMQ()
{
::DeleteCriticalSection(&m_lock);
::CloseHandle(m_hPushEvent);
::CloseHandle(m_hPopEvent);
m_list.RemoveAll();
}
// 队列尾增加消息,如果消息队列已满,根据设定或丢弃消息,或阻塞直到队列不为满的时候。
void Push(TYPE& type)
{
::EnterCriticalSection(&m_lock);
// 如果消息队列已满
if ( m_nMax > 0 && m_list.GetCount() >= m_nMax)
{
::ResetEvent(m_hPushEvent);
::LeaveCriticalSection(&m_lock);
if( m_bDrop )
return;
if ( ::WaitForSingleObject(m_hPushEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
::EnterCriticalSection(&m_lock);
}
m_list.AddTail(type);
::SetEvent(m_hPopEvent);
::LeaveCriticalSection(&m_lock);
}
// 队列头增加消息,如果消息队列已满,根据设定或丢弃消息,或阻塞直到队列不为满的时候。
void Insert(TYPE& type)
{
::EnterCriticalSection(&m_lock);
// 如果消息队列已满
if ( m_nMax > 0 && m_list.GetCount() >= m_nMax)
{
::ResetEvent(m_hPushEvent);
::LeaveCriticalSection(&m_lock);
if( m_bDrop )
return;
if ( ::WaitForSingleObject(m_hPushEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
::EnterCriticalSection(&m_lock);
}
m_list.AddHead(type);
::SetEvent(m_hPopEvent);
::LeaveCriticalSection(&m_lock);
}
// 从队列头中取消息,如果队列为空则阻塞,直到不为空的时候。
TYPE Pop()
{
TYPE type;
::EnterCriticalSection(&m_lock);
// 如果队列为空
if (m_list.IsEmpty())
{
::ResetEvent(m_hPopEvent);
::LeaveCriticalSection(&m_lock);
if ( ::WaitForSingleObject(m_hPopEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
::EnterCriticalSection(&m_lock);
}
type = m_list.RemoveHead();
::SetEvent(m_hPushEvent);
::LeaveCriticalSection(&m_lock);
return type;
}
// 返回目前消息队列中的消息个数。
int GetQueueCount()
{
int nCount = 0;
::EnterCriticalSection(&m_lock);
nCount = m_list.GetCount();
::LeaveCriticalSection(&m_lock);
return nCount;
}
// 设置消息队列的最大长度,以及如果消息队列满的时候新消息的处理方式。
// 或丢弃消息,或阻塞直到队列不为满的时候。
void SetMaxCount(int nMax = -1, BOOL bDrop = FALSE)
{
::EnterCriticalSection(&m_lock);
m_nMax = nMax;
m_bDrop = bDrop;
::LeaveCriticalSection(&m_lock);
}
// 返回消息队列的最大长度,如果没有设置最大长度则返回-1。
int GetMaxCount()
{
::EnterCriticalSection(&m_lock);
::LeaveCriticalSection(&m_lock);
return m_nMax;
}
private:
CRITICAL_SECTION m_lock;
CList m_list;
HANDLE m_hPopEvent;
HANDLE m_hPushEvent;
int m_nMax;
BOOL m_bDrop;
};
#endif // CHMQ_H
http://blog.csdn.net/Thinkry/archive/2004/09/02/92327.aspx
seven2000收录,使用标签:算法, 生产者消费者,时间:2008-8-7 18:22:21 | 相关网摘,我也收藏
生产者-消费者模型的解决思路——自建队列收藏
新一篇: 用JScript实现MembersTable | 旧一篇: 在Web上用style实现完美颜色渐变
笔者曾遇到这样的需求:某软件在运行中随时有可能向外发送短信,一方面发送短信的设备是个独占资源,另一方面有多个线程要发短信。按照“把不稳定因素限定在一个实体中”的原则,自然就用一个专门的线程来操作短信设备,它的任务是从消息队列中取出要发送的短信,通过短信设备发送出去。
这是比较常见的生产者-消费者模型,即一个模块产生数据,另外模块取得数据并进行处理。如何实现互斥?如何让生产者和消费者都能够方便的工作?
类似这样的情况在编程中十分常见,采用消息队列是很好的解决办法。本文给出的消息队列具有以下特色:
·消息的大小、结构是自由的,甚至可以是一个对象;
·消息队列的长度(容纳消息的个数)是可设定的,超过最大长度可以选择丢弃或等待;
·新消息一般是放在队列的最后面,也可以放在最前面;
·代码少,思路简洁,你可以根据情况扩展;
【设计思路】
设计思路其实很简单,消息队列类CHMQ是个模板类,用CList保存消息,用CriticalSection来实现互斥,用Event来控制消息队列为空或已满的情况。提供以下几个常用接口:
·Push() 在队列尾增加消息,如果消息队列已满,根据设定或丢弃消息,或阻塞直到队列不为满的时候。
·Insert() 在对列头增加消息,其他同Push()。
·Pop() 从队列头中取消息,如果队列为空则阻塞,直到不为空的时候。
·SetMaxCount() 设置消息队列的最大长度,以及如果消息队列满的时候新消息的处理方式。 或丢弃消息,或阻塞直到队列不为满的时候。
·GetMaxCount() 返回消息队列的最大长度,如果没有设置最大长度则返回-1。
·GetQueueCount() 返回目前消息队列中的消息个数。
【扩展】
(1) 目前一个CHMQ对象仅支持一个消息队列,可以扩展成多个消息队列
(2) 消息队列为空时,Pop()一直阻塞到有新消息时才返回,可以扩展成超时返回
(3) 消息队列已满时,Push()和Insert()可能会阻塞到队列不满的时候,可以扩展成超时丢弃
#ifndef CHMQ_H
#define CHMQ_H
#include
#include
template
class CHMQ
{
public:
CHMQ()
{
m_nMax = -1;
m_bDrop = FALSE;
::InitializeCriticalSection(&m_lock);
m_hPushEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT(m_hPushEvent != NULL);
m_hPopEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT(m_hPopEvent != NULL);
}
~CHMQ()
{
::DeleteCriticalSection(&m_lock);
::CloseHandle(m_hPushEvent);
::CloseHandle(m_hPopEvent);
m_list.RemoveAll();
}
// 队列尾增加消息,如果消息队列已满,根据设定或丢弃消息,或阻塞直到队列不为满的时候。
void Push(TYPE& type)
{
::EnterCriticalSection(&m_lock);
// 如果消息队列已满
if ( m_nMax > 0 && m_list.GetCount() >= m_nMax)
{
::ResetEvent(m_hPushEvent);
::LeaveCriticalSection(&m_lock);
if( m_bDrop )
return;
if ( ::WaitForSingleObject(m_hPushEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
::EnterCriticalSection(&m_lock);
}
m_list.AddTail(type);
::SetEvent(m_hPopEvent);
::LeaveCriticalSection(&m_lock);
}
// 队列头增加消息,如果消息队列已满,根据设定或丢弃消息,或阻塞直到队列不为满的时候。
void Insert(TYPE& type)
{
::EnterCriticalSection(&m_lock);
// 如果消息队列已满
if ( m_nMax > 0 && m_list.GetCount() >= m_nMax)
{
::ResetEvent(m_hPushEvent);
::LeaveCriticalSection(&m_lock);
if( m_bDrop )
return;
if ( ::WaitForSingleObject(m_hPushEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
::EnterCriticalSection(&m_lock);
}
m_list.AddHead(type);
::SetEvent(m_hPopEvent);
::LeaveCriticalSection(&m_lock);
}
// 从队列头中取消息,如果队列为空则阻塞,直到不为空的时候。
TYPE Pop()
{
TYPE type;
::EnterCriticalSection(&m_lock);
// 如果队列为空
if (m_list.IsEmpty())
{
::ResetEvent(m_hPopEvent);
::LeaveCriticalSection(&m_lock);
if ( ::WaitForSingleObject(m_hPopEvent, INFINITE) != WAIT_OBJECT_0)
ASSERT(FALSE);
::EnterCriticalSection(&m_lock);
}
type = m_list.RemoveHead();
::SetEvent(m_hPushEvent);
::LeaveCriticalSection(&m_lock);
return type;
}
// 返回目前消息队列中的消息个数。
int GetQueueCount()
{
int nCount = 0;
::EnterCriticalSection(&m_lock);
nCount = m_list.GetCount();
::LeaveCriticalSection(&m_lock);
return nCount;
}
// 设置消息队列的最大长度,以及如果消息队列满的时候新消息的处理方式。
// 或丢弃消息,或阻塞直到队列不为满的时候。
void SetMaxCount(int nMax = -1, BOOL bDrop = FALSE)
{
::EnterCriticalSection(&m_lock);
m_nMax = nMax;
m_bDrop = bDrop;
::LeaveCriticalSection(&m_lock);
}
// 返回消息队列的最大长度,如果没有设置最大长度则返回-1。
int GetMaxCount()
{
::EnterCriticalSection(&m_lock);
::LeaveCriticalSection(&m_lock);
return m_nMax;
}
private:
CRITICAL_SECTION m_lock;
CList m_list;
HANDLE m_hPopEvent;
HANDLE m_hPushEvent;
int m_nMax;
BOOL m_bDrop;
};
#endif // CHMQ_H
http://blog.csdn.net/Thinkry/archive/2004/09/02/92327.aspx
seven2000收录,使用标签:算法, 队列,时间:2008-8-7 18:13:07 | 相关网摘,我也收藏
按照《算法导论》中给出的操作来封装的,支持最大优先级和最小优先级队列,大部分添加在了头文件中,包含了各个接口的用法。
data_struct.c
#include
#include
#include
#include "data_struct.h"
/* 封装优先级队列(使用堆结构) */
/******************************/
static inline int LEFT_PQ(int index) //节点下标为index左孩子的下标
{
return (index << 1) + 1;
}
static inline int RIGHT_PQ(int index) //节点下标为index的右孩子的下标
{
return (index << 1) + 2;
}
static inline int PARENT_PQ(int index) //节点下标为index的父节点的下标
{
return (index - 1) / 2;
}
/* 保持堆的性质,此函数实现将某个子树的根节点按照堆的性质下降到某个子孙节点 */
static void HEAPIFY_PQ(PQ *desc, int index)
{
int left = LEFT_PQ(index);
int right = RIGHT_PQ(index);
int largest;
PQ_element *tmp = NULL;
for (; left < desc->heap_size || right < desc->heap_size;
left = LEFT_PQ(index), right = RIGHT_PQ(index)) {
if (left < desc->heap_size &&
desc->compar(desc->base[left]->data, desc->base[index]->data) > 0)
largest = left;
else largest = index;
if (right < desc->heap_size &&
desc->compar(desc->base[right]->data, desc->base[largest]->data) > 0)
largest = right;
if (largest == index)
break;
tmp = desc->base[index];
tmp->index = largest;
desc->base[largest]->index = index;
desc->base[index] = desc->base[largest];
desc->base[largest]= tmp;
index = largest;
}
}
/* 分配一个节点 */
PQ_element *malloc_PQ(size_t size)
{
PQ_element *e = NULL;
e = malloc(sizeof(PQ_element));
if (e == NULL)
goto end;
e->data = malloc(size);
if (e->data == NULL) {
free(e);
e = NULL;
}
e->index = -1;
end:
return e;
}
void free_PQ(PQ_element *ptr)
{
PQ_element *e = (PQ_element *)ptr;
if (!e)
return;
if (!(e->data)) {
free(e);
return;
}
free(e->data);
free(e);
}
PQ *create_PQ(int nmemb, compar_t compar, change_key_t change_key)
{
PQ *ret = NULL;
PQ_element *t = NULL;
ret = (PQ *)malloc(sizeof(PQ));
if (ret == NULL) {
goto end;
}
ret->compar = compar;
ret->change_key = change_key;
ret->heap_size = 0;
ret->len = nmemb;
t = malloc(sizeof(PQ_element *) * nmemb);
if (t == NULL) {
free(ret);
ret = NULL;
goto end;
}
memset(t, 0, sizeof(PQ_element *) * nmemb);
ret->base = (PQ_element **)t;
end:
return ret;
}
void destroy_PQ(PQ *desc)
{
if (!desc)
return;
if (desc->base)
free(desc->base);
free(desc);
}
int insert_PQ(PQ *desc, PQ_element *x)
{
PQ_element *tmp = NULL;
int ret = -1, i;
if (desc->heap_size >= desc->len) {
tmp = realloc(desc->base, sizeof(PQ_element *) * (desc->len + 5));
if (tmp == NULL) {
goto end;
}
memset(&tmp[desc->len], 0, sizeof(PQ_element *) * 5);
desc->base = (PQ_element **)tmp;
desc->len += 5;
}
x->index = desc->heap_size;
desc->base[desc->heap_size] = x;
desc->heap_size++;
i = x->index;
while (i > 0 && desc->compar(desc->base[PARENT_PQ(i)]->data, desc->base[i]->data) < 0) {
tmp = desc->base[i];
tmp->index = PARENT_PQ(i);
desc->base[PARENT_PQ(i)]->index = i;
desc->base[i] = desc->base[PARENT_PQ(i)];
desc->base[PARENT_PQ(i)] = tmp;
i = PARENT_PQ(i);
}
ret = 0;
end:
return ret;
}
int delete_PQ(PQ *desc, const PQ_element *x)
{
int i = x->index;
desc->base[i] = desc->base[desc->heap_size - 1];
desc->base[desc->heap_size - 1] = NULL;
desc->base[i]->index = i;
desc->heap_size--;
HEAPIFY_PQ(desc, i);
return 0;
}
PQ_element *root_PQ(PQ *desc)
{
if (desc && desc->base)
return desc->base[0];
return NULL;
}
PQ_element *extract_PQ(PQ *desc)
{
if (!desc || !(desc->base))
return NULL;
if (desc->heap_size <= 0)
return NULL;
PQ_element *max = desc->base[0];
desc->base[0] = desc->base[desc->heap_size - 1];
desc->base[desc->heap_size - 1] = NULL;
if (desc->base[0])
desc->base[0]->index = 0;
desc->heap_size--;
HEAPIFY_PQ(desc, 0);
return max;
}
void change_key_PQ(PQ *desc, PQ_element *x, const void *key)
{
int i = x->index;
PQ_element *tmp = NULL;
desc->change_key(x->data, key);
while (i > 0 && desc->compar(desc->base[PARENT_PQ(i)]->data, desc->base[i]->data) < 0) {
tmp = desc->base[i];
tmp->index = PARENT_PQ(i);
desc->base[PARENT_PQ(i)]->index = i;
desc->base[i] = desc->base[PARENT_PQ(i)];
desc->base[PARENT_PQ(i)] = tmp;
i = PARENT_PQ(i);
}
}
/******************************/
data_struct.h
#ifndef DATA_STRUCT___H
#define DATA_STRUCT___H
/* 用户自定义比较函数 */
typedef int (*compar_t)(const void *, const void *);
/* 用户自定义修改关键字函数,
* 前者参数为用户自定义数据结构,
* 后者参数为要修改的key值
*/
typedef void (*change_key_t)(void *, const void *);
/* 队列元素结构 */
typedef struct pq_element
{
void *data;
int index; //用于记录该节点所位于数组中的下标值
}PQ_element;
typedef struct PQ_desc
{
compar_t compar;
change_key_t change_key;
int heap_size; /* 堆的大小 */
int len; /* 当前优先级队列数组中可容纳的最大长度 */
PQ_element **base;
}PQ;
/* 创建优先级队列,nmemb为队列中包含元素的个数,compar为比较函数,change_key为修改关键字函数 */
PQ *create_PQ(int nmemb, compar_t compar, change_key_t change_key);
void destroy_PQ(PQ *desc); //销毁优先级队列
int insert_PQ(PQ *desc, PQ_element *x); //向队列中插入一个元素,元素为前面定义的元素结构
int delete_PQ(PQ *desc, const PQ_element *x); //删除队列中的一个元素,该元素由x引用
PQ_element *root_PQ(PQ *desc); //得到优先级队列的对头元素
PQ_element *extract_PQ(PQ *desc); //得到优先级队列的对头元素并将对头元素从优先级队列中删除
/*
* 将key指向的用户结构赋值给x指向的用户结构,并改变x在队列中的位置
* 这里将调用用户自定义的change_key函数,
* 并将key和x做为change_key函数的参数传递
*/
void change_key_PQ(PQ *desc, PQ_element *x, const void *key); //将优先级队列desc中的元素x中的关键字修改为key
PQ_element *malloc_PQ(size_t size); //申请节点空间
void free_PQ(PQ_element *ptr); //释放由malloc_PQ申请的节点空间.
#define ELEMENT_DATA(pq_element) ((pq_element)->data) //返回节点元素中用户自定义数据结构的指针
#define CLEAN_ELEMENT(pq_element) ((pq_element)->data = NULL) //将节点元素中的用户数据指针清除
#define INDEX_ELEMENT(pq_element) ((pq_element)->index) //返回节点元素在堆中的索引值
#define PQ_SIZE(desc) ((desc)->heap_size) //优先级队列中队列的长度
#define PQ_LEN(desc) ((desc)->len) //目前能容纳的元素的最大个数
#endif
http://blog.chinaunix.net/u/24478/showart_508693.html
seven2000收录,使用标签:算法, 队列,时间:2008-8-7 18:07:46 | 相关网摘,我也收藏
一种同步消息队列模型
在已故巨匠Stevens先生中的<>中有记载使用互斥锁和条件变量来解决生产者/消费者的方法,在多线程编程中,我们也常常需要解决这样的生产者消费者问题。在实际项目中,我见到过很多种解决类似问题的同步消息队列,有的复杂而优雅,有得简陋而实用。
对于生产者,如果不考虑内存和队列的大小问题,只需要一直往消息队列里推消息就可以了。而对于消费者就要复杂一点了,在消息队列取空后,消费者可以循环轮询队列,直到取到新的消息,这种方式编码简单,但是浪费CPU时间片; 更加优雅的方法是当消息队列为空时,将消费者挂起,等到有消息可读时再唤醒。
这里引用Stevens先生的方法,使用互斥锁和信号量实现了一个简单的同步消息队列模型。
#include
#include
#include
#include
#include
#include
using namespace std;
template
class Message_Queue
{
public:
//构造函数,初始化2个互斥锁和1个条件变量
Message_Queue():_nready(0)
{
pthread_mutex_init(&_mutex, NULL);
pthread_mutex_init(&_ready_mutex, NULL);
pthread_cond_init(&_cond, NULL);
}
//推消息
int push_msg(DataType &d)
{
//加锁_mutex,向queue里推消息
pthread_mutex_lock(&_mutex);
_queue.push_back(d);
pthread_mutex_unlock(&_mutex);
//加锁_ready_mutex,判断是否需要唤醒挂起的消费者
pthread_mutex_lock(&_ready_mutex);
if (!_nready)
pthread_cond_signal(&_cond); //唤醒阻塞在此消息队列上的消费者
_nready++; //计数器++
pthread_mutex_unlock(&_ready_mutex);
return 0;
}
//取消息
int get_msg(DataType &d)
{
//加锁,查看计数器,看是否需要挂起
pthread_mutex_lock(&_ready_mutex);
while (_nready == 0) //计数器为0,队列为空,挂起
pthread_cond_wait(&_cond, &_ready_mutex); //为空时,所有消费者会阻塞在此
//当被生产者唤醒时,消费者重新加_ready_mutex锁,_nready > 0, 程序跳出while(_nready)循环继续运行
_nready--;
pthread_mutex_unlock(&_ready_mutex);
//加锁,取队列操作
pthread_mutex_lock(&_mutex);
d = _queue.front();
_queue.pop_front();
pthread_mutex_unlock(&_mutex);
return 0;
}
private:
pthread_cond_t _cond;
int _nready;
pthread_mutex_t _ready_mutex;
pthread_mutex_t _mutex;
deque _queue;
};
//测试程序,模拟N个生产者和M个消费者使用消息队列同时工作的情况。
void *consume(void *arg) //消费者线程
{
Message_Queue *queue = (Message_Queue *)arg;
int i;
for (; ; )
{
sleep(1);
printf("[%u]ready to get_msg\n", pthread_self());
queue->get_msg(i);
printf("[%u]get msg = %d\n", pthread_self(), i);
}
}
void *produce(void *arg) //生产者线程
{
Message_Queue *queue = (Message_Queue *)arg;
int i;
for (; ; )
{
sleep(1);
printf("[%u]ready to push_msg\n", pthread_self());
queue->push_msg(i);
printf("[%u]push_msg finished\n", pthread_self());
i++;
}
}
int main()
{
Message_Queue msg_queue;
int n ;
int c = 2;
int p = 3;
pthread_t k;
printf("create %d consume................\n", c);
for (n=0; n< c; n++)
{
pthread_create(&k, NULL, consume, &msg_queue);
}
printf("create %d produce.............\n", p);
for (n=0; n< p; n++)
{
pthread_create(&k, NULL, produce, &msg_queue);
}
pause();
}
这样,我们对STL的deque 进行一个简单的封装,就获得了一个可用的同步消息队列。这里需要提及的是,一次pthread_cond_signal操作会唤醒所有阻塞在此条件变量上的消费者,而所有阻塞在pthread_cond_wait上的消费者被唤醒,这就是所谓“惊群”。而被唤醒的所有消费者都会去竞争_ready_mutex锁,这就是所谓“二次竞争”。这样的“惊群”和“二次竞争”在各个平台上是否存在,对性能的影响有多大,我没有验证过,只是一种猜测,不过相信这样的模型满足一般的应用程序应该没有问题。
http://blog.chinaunix.net/u1/52242/showart_725095.html
共719个网摘 [
1 2 3 4 5 6 7 8 ...
24 ]
上一页 |
下一页