我如何编码以保持我的程序中的8个线程始终处于活动状态?

时间:2014-01-22 17:41:57

标签: c++ multithreading pthreads

我的代码必须独立处理几百个文件。我想让我的程序始终处理8个线程。一旦其中一个线程完成,我想启动一个处理新文件的新线程,而不会阻塞我的代码,直到最后完成所有线程。

我在linux上使用pthread。

我不知道如何编码。 pthread_join()阻止代码执行?我如何知道一个线程何时完成?这段代码是如何执行的?

pthread_join(thread1)
pthread_join(thread2)

thread1必须在pthread_join(thread2)执行之前完成吗?

所以,如果我放置

for (i=0;i<7;i++)
    pthread_join(thread[i])
cout<<"Here!";

这是否意味着我必须在打印Here!之前等待所有线程完成?

或者我根本不应该使用pthreads?

3 个答案:

答案 0 :(得分:5)

创建新线程需要付出代价,并且没有理由为每个文件生成新线程。此外,还有额外的工作需要跟踪这些线程,以便您可以在需要时加入它们。

更好的方法是拥有一个同步队列。主线程将插入作业(例如,路径),您的工作线程可以从队列中读取并处理每个文件。工作线程将阻塞,直到将作业插入队列。

如果您无权访问同步队列,则通过在操作上使用互斥锁来创建一个队列应该相当容易。

pthread_join确实会阻塞,直到提供的线程完成。因此,在您的示例中,必须完成所有线程才能进行打印。

如果你真的想在每次死亡时产生一个新线程 - 你可以在从线程执行的函数返回之前调用一些函数。此函数将生成一个新线程,该线程将处理下一个文件。处理完所有文件后,线程编号将自动减少。

答案 1 :(得分:2)

  

是否pthread_join()阻止代码执行?

是的,它专门等待联接线程完成执行,并返回其退出代码。因此,调用线程将阻塞,直到发生这种情况。

您会注意到documentation对此非常明确:

  

pthread_join()函数将暂停执行调用线程,直到目标线程终止


正如Vadim所说,正确的方法通常是每个核心有一个长期存在的线程,并使用队列或类似的东西向你的线程/核心发送工作。一直停止和启动线程是低效的。

换句话说,线程不是任务。线程一个接一个地执行任务。

请注意,您的文件系统是否能够真正保持8个并发线程的忙碌取决于您正在做什么:文件访问可能会通过驱动程序进行序列化,如果您最终受到I / O而不是CPU的限制,许多线程可能不是最有效的方法。

答案 2 :(得分:1)

请原谅我的无知,但我认为拥有多个线程来阅读文件没有任何好处。

设备I / O瓶颈
除非您的计算机每个硬盘都有一个单独的I / O通道,并且每个文件位于单独的磁盘上,否则您的性能瓶颈之一就是I / O通道。大多数计算机一次只能读取一个通道,或者可能将多个消息多路复用到硬盘驱动器。

推动搜寻位置
在一个文件是一组连续扇区的理想情况下,您将有两个搜索操作:目录查找和文件打开。驱动器将提供所有数据,而无需重新定位头部。

当您在单个硬盘驱动器上同时读取多个文件时,硬盘驱动器必须寻找一个文件,读取一些数据,搜索第二个文件,读取一些数据等等,直到它循环到第一个文件。对于每个读取的数据块,每个文件至少有一个搜索操作。从而积累了大量的时间寻求硬盘中的各个地方。

多核一个I / O通道
在内部,数据必须从硬盘驱动器进入PC的内存。然后,相应的内核必须使用单个数据总线或单个内存区域来获取其数据。想象一下带有交通信号的单车道。每个核心都将被阻塞(等待),直到数据总线(道路)可用。因此等待时间更长。

线程切换开销
与线程相关的成本:创建和切换。即使每个处理器的比率为一个线程,操作系统也必须协调和管理线程。从本质上讲,每个线程都会增加一个簿记成本,从计算机的性能和内存空间中减去。

一个I / O线程,多个处理线程。 高性能文件的目标是保持硬盘旋转并减少搜索操作的数量。在线程上可以轻松实现这一点。

为每个处理线程分配一个缓冲区将有助于提高性能。文件读取线程将为处理线程填充一个缓冲区并继续下一个。具有多个处理器或内核的系统优化了数据总线共享;所以每个核心花费最少的时间被阻止。

核心缓存
处理线程应尽可能多地从I / O缓冲区获取数据到处理器的数据缓存中。这允许一个核心从其缓存处理数据,而另一个核心从I / O缓冲区加载其缓存。

物理优化
一些大学实验表明,通过对系统进行物理更改,可以显着提高性能。一个例子是为每个数据位使用一个硬盘驱动器。其他系统使用许多硬盘驱动器并将文件分布在许多硬盘驱动器上以减轻对单个驱动器的需求。有些系统实际上有多个I / O通道存储器。直接内存访问(DMA)控制器可以在处理器执行其他操作时将数据从I / O端口提取到内存中。

<强>摘要 我建议在扩展到多个读取线程之前先使用一个读取线程进行优化。处理数据可能受益于其他线程。通过优化线程以使用CPU数据高速缓存和指令管道,您将获得更明显的性能提升。