多线程文件搜索
Multithreaded file search
我想知道我应该如何解决以下问题。我的 c 程序将收到 3 个参数 - 路径、术语和要调用的线程数 。
我应该在 路径 的任何子目录中探索名称中包含 术语 的文件。如果我的程序是异步的,那将是一项相当容易的工作。
我正在为我的线程使用共享的队列,带有锁和条件变量 同步。
我的逻辑如下 -
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..)
}
这与其说是真正的代码不如说是伪代码,但我更担心我的逻辑而不是我的实现。
我的问题是,我如何向我的线程发出空队列信号以结束它们的功能,这不仅仅是临时的,直到队列将包含一些路径。
我很想听听您的意见!
I'm more worried about my logic than my implementation. My question
is, how can i signal my threads that empty queue signals to end their
function, and it's not just temporary until the queue will contain
some path.
我想您是在问如何处理队列为空并不构成适当的线程终止条件这一事实,因为新目录可能会被任何仍处于活动状态的线程排队。答案很简单:不要使用队列空作为(唯一)终止条件。相反,维护另一个共享变量来跟踪当前处理目录的线程数——也在互斥锁的保护下——并使循环终止条件为队列为空和没有线程正在处理目录。
另请注意,您必须
- 注意确保所有 对共享状态的访问都受到互斥体的保护。在循环条件中包括队列空测试。
- 注意尽可能限制互斥量的范围,以允许最大的并发量。
- 准备好处理虚假唤醒。
逻辑可能看起来更像这样:
// ...
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..)
}
我想知道我应该如何解决以下问题。我的 c 程序将收到 3 个参数 - 路径、术语和要调用的线程数 。
我应该在 路径 的任何子目录中探索名称中包含 术语 的文件。如果我的程序是异步的,那将是一项相当容易的工作。
我正在为我的线程使用共享的队列,带有锁和条件变量 同步。
我的逻辑如下 -
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..)
}
这与其说是真正的代码不如说是伪代码,但我更担心我的逻辑而不是我的实现。 我的问题是,我如何向我的线程发出空队列信号以结束它们的功能,这不仅仅是临时的,直到队列将包含一些路径。
我很想听听您的意见!
I'm more worried about my logic than my implementation. My question is, how can i signal my threads that empty queue signals to end their function, and it's not just temporary until the queue will contain some path.
我想您是在问如何处理队列为空并不构成适当的线程终止条件这一事实,因为新目录可能会被任何仍处于活动状态的线程排队。答案很简单:不要使用队列空作为(唯一)终止条件。相反,维护另一个共享变量来跟踪当前处理目录的线程数——也在互斥锁的保护下——并使循环终止条件为队列为空和没有线程正在处理目录。
另请注意,您必须
- 注意确保所有 对共享状态的访问都受到互斥体的保护。在循环条件中包括队列空测试。
- 注意尽可能限制互斥量的范围,以允许最大的并发量。
- 准备好处理虚假唤醒。
逻辑可能看起来更像这样:
// ...
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..)
}