首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 .NET Java 游戏 视频 人才 外包 数据库 第二书店 程序员

Tag/ 


共719个网摘 [ 1  2  3  4  5  6  7  8 ... 24 ]  上一页 | 下一页  |  

擂台:超大整数高精度快速算法-4 (快速计算千万阶乘)

insulted收录,使用标签:算法,时间:2008-9-3 10:44:03 | 相关网摘我也收藏

]


加为好友
发送私信
在线聊天
gxqcn
www.emath.ac.cn
等级:
gxqcn ()发表于:2007-07-11 22:22:05 楼主
近几个月来,我把精力主要集中于改进大数算法


关于循环小数的问题

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)


生产者-消费者模型的解决思路——自建队列 - Thinkry的Blog专栏 - CSDNBlog

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


算法的力量 - familyX的专栏 - CSDNBlog

tqjs收录,使用标签:算法,时间:2008-8-21 11:22:07 | 相关网摘我也收藏

介绍算法的重要性及要学习的基础课程及对程序员的建议


推荐系统:关联规则(3) —— FP-Growth 算法

zdg收录,使用标签:Recommend, 算法,时间:2008-8-18 18:25:29 | 相关网摘我也收藏

FP-Growth 算法的核心是 FP-Tree(Frequent Pattern Tree,频繁模式树)的构建,这个特殊的数据结构,是 FP-Growth 算法与 Apriori 算法相比,性能显著提高的原因所在。不过,仔细分析一下 FP-Tree 的实现,可以发现它与字符串处理算法中常用的 Prefix Tree 算法,有着异曲同工之妙。FP-Tree 通过合并一些重复路径,实现了数据的压缩,从而使得将频繁项集加载到内存中成为可能。之后以树遍历的操作,替代了 Apriori 算法中最耗费时间的事务记录遍历,从而大大提高了运算效率。


生产者-消费者模型的解决思路——自建队列 - Thinkry的Blog专栏 - CSDNBlog

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


封装优先级队列 - 数学及算法 - cugb_cat

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


一种同步消息队列模型 - 长江七号

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锁,这就是所谓“二次竞争”。这样的“惊群”和“二次竞争”在各个平台上是否存在,对性能的影响有多大,我没有验证过,只是一种猜测,不过相信这样的模型满足一般的应用程序应该没有问题。




共719个网摘 [ 1  2  3  4  5  6  7  8 ... 24 ]  上一页 | 下一页

Tag/相关标签



    网站简介广告服务网站地图帮助联系方式诚聘英才English 问题报告
    北京创新乐知广告有限公司 版权所有 京 ICP 证 070598 号
    Copyright © 2000-2008, CSDN.NET, All Rights Reserved