首页 > 解决方案 > 多线程文件搜索

问题描述

我想知道我应该如何解决以下问题。我的 c 程序将接收 3 个参数 -路径、术语和要调用的线程数。

我应该在path的任何子目录中探索名称中包含该术语的文件。如果我的程序是异步的,那将是一项相当容易的工作。

我正在为我的线程使用共享队列,并使用条件变量进行同步。

我的逻辑如下 -

int main(int argc, char *argv)
{
 ...
Queue *queue = init_queue();
enqueue(queue, root_path);    

for (int i = 0; i<n_threads; ++i)
    pthread_create(..., thread_handle, ...);
 ...
}

void thread_handle()
{

    while (!queue_empty)
    {
          while(!condition_variable)
              pthread_cond_wait(&cond);
          pthread_mutex_lock(&lock);
          QNode *node = dequeue(queue);  
          iterate_dir(node->path);
          pthread_mutex_unlock(&lock);
          thread_cond_signal(condition_variable);
    }
}

void iterate_dir(...)
{
    // Directory search logic (with enqueue..)
}

这是一个伪代码而不是真正的代码,但我更担心我的逻辑而不是我的实现。我的问题是,我如何向我的线程发出空队列信号以结束其功能的信号,并且在队列包含某些路径之前,这不仅仅是暂时的。

我很想听听你的意见!

标签: cmultithreadingpthreads

解决方案


我更担心我的逻辑而不是我的实现。我的问题是,我如何向我的线程发出空队列信号以结束其功能的信号,并且在队列包含某些路径之前,这不仅仅是暂时的。

我认为您在问如何处理队列为空不构成适当的线程终止条件的事实,因为新目录可能被仍然处于活动状态的任何线程排队。答案很简单:不要使用队列空作为(唯一的)终止条件。相反,维护另一个共享变量来跟踪当前处理目录的线程数——也在互斥锁的保护下——并使循环终止条件为队列为空没有线程正在处理目录。

另请注意,您必须

  • 注意确保对共享状态的所有访问都受到互斥锁的保护。在循环条件中包括队列空测试。
  • 注意尽可能限制互斥体的范围,以允许最大的并发量。
  • 准备好处理虚假唤醒。

逻辑可能看起来更像这样:

// ...

int num_active_threads = 0;

void *thread_handle(void *arg) {
    pthread_mutex_lock(&lock);
    while (true) {
        while (queue_empty && num_active_threads > 0) {
                pthread_cond_wait(&cond);
        }
        if (queue_empty) break; // it must (also) be that num_active_threads == 0, so all done
        QNode *node = dequeue(queue);  
        num_active_threads++;
        pthread_mutex_unlock(&lock);

        iterate_dir(node->path);

        pthread_mutex_lock(&lock);
        num_active_threads--;
        pthread_cond_broadcast(condition_variable);
    }
    pthread_mutex_unlock(&lock);
}

void iterate_dir(...)
{
    // Directory search logic (with MUTEX-PROTECTED enqueue..)
}

推荐阅读