我有一个单链表,每个元素包含1个值。
struct listElement
{
char guid[20];
struct listElement *next;
struct listElement *last;
int numElements;
};
代码在池中启动10个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()
之外,还有更好的方法来限制列表的大小吗?
答案 0 :(得分:0)
是的,而不是使用睡眠,您可以等待信号量(类似于互斥量,但以其他方式),并在将新元素添加到列表时唤醒。您可能能够找到事件库或使用pthreads自己完成。
答案 1 :(得分:0)
这听起来像是经典producer-consumer problem。如果列表太大,解决方案是让listPush()
等待条件变量。然后,一旦使用了列表元素,其中一个消费者线程就会发出这个条件变量的信号。
完全不同的方法是使用pipe()
来处理通信和同步。这样就不需要链表和互斥锁。