>我有一个单链表,每个元素包含 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 自己完成。