1

我有一个单链表,每个元素中包含 1 个值。

struct listElement
{
    char guid[20];
    struct listElement *next;
    struct listElement *last;
    int numElements;
};

该代码在一个池中启动了 10 个 pthread,所有这些 pthread 都是pthread_cond_wait()为了将​​一个元素添加到列表中。

我的 main() 正在从文件中读取字符串,一次一行并通过调用填充链表listPush(val)

listPush(val)获取锁,创建新元素,添加到列表末尾(如果为空则创建头部)解锁然后调用pthread_cond_signal()让 10 个线程之一知道现在有一个元素需要完成。

在 numElements > numThreads 我调用的情况下,pthread_cond_broadcast()因为每个线程应该有足够的工作来弹出和执行。

每个线程都listPop(rVal)关闭一个值(锁定、删除、修复指针、解锁)并对其进行处理,然后返回pthread_cond_wait()状态。

我的文件有大约 2 亿行。(1.2GB) 我不希望我的链表变得这么大,所以我试图“限制”链表的大小。

在里面listPush(),在我锁定互斥锁之前,我有

if(head && head->numElements >= maxNumElements)
{
    while(head && head->numElements >= maxNumElements)
    {
        sleep(1);
    }
}

这个想法是,如果我“填满”我的列表,我会等待线程处理其中的一部分,然后再添加更多。我已经到了应用程序开始“跳动”的地步;基本上我可以看到它等待 1 秒。我希望这永远不会发生或很少发生。

除了使用之外,还有更好的方法来限制我的列表的大小sleep()吗?

4

2 回答 2

0

是的,您可以在信号量上等待(类似于互斥体,但以另一种方式),而不是使用睡眠,并在将新元素添加到列表时被唤醒。您可能能够找到一个事件库或使用 pthreads 自己做。

于 2012-06-16T19:28:55.547 回答
0

这听起来像是一个经典的生产者-消费者问题listPush()如果列表太大,解决方案是等待条件变量。然后,一旦使用了列表元素,其中一个消费者线程就可以向这个条件变量发出信号。

一种完全不同的方法是只使用 apipe()来处理通信和同步。这将消除对链表和互斥体的需要。

于 2012-06-16T19:29:04.573 回答