填充大小列表,pthreads弹出列表

populating list at size with pthreads popping off list

本文关键字:列表 pthreads 填充      更新时间:2023-10-16

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

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

该代码在池中启动 10 个 pthread,这些线程都pthread_cond_wait()元素添加到列表中。

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

listPush(val)获取 lock,创建新元素,添加到列表末尾(如果为空则创建 head),然后调用 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() 之外,有没有更好的方法来限制我的列表的大小?

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

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

是的,与其使用睡眠,不如等待信号量(类似于互斥锁,但以另一种方式),并在将新元素添加到列表时被唤醒。您也许可以找到事件库或使用 pthreads 自己完成。