返回

如何使用条件变量周期性触发并等待 pthread 工作线程完成?

Linux

周期性触发和等待完成 pthread 工作线程

简介

在多线程编程中,经常需要协调多个线程的执行,以确保任务以特定顺序或周期性地执行。本文将探讨如何使用条件变量来周期性地触发一组 pthread 工作线程并等待它们全部完成。

使用条件变量

条件变量是一种线程同步机制,允许一个线程等待特定条件满足,然后继续执行。在我们的场景中,条件是所有工作线程都已完成其任务。

以下步骤演示了如何使用条件变量实现此功能:

1. 创建条件变量和互斥锁

首先,我们需要创建一个条件变量 cond 和一个互斥锁 mutex。互斥锁用于保护对共享数据(条件变量)的访问。

pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_cond_init(&cond, NULL);
pthread_mutex_init(&mutex, NULL);

2. 在工作线程中

每个工作线程在完成任务后应执行以下步骤:

  • 获取互斥锁以保护条件变量。
  • 信号条件变量,表示已完成任务。
  • 释放互斥锁。
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);

3. 在主线程中

主线程负责触发工作线程并等待它们完成。它将执行以下步骤:

  • 触发工作线程。
  • 获取互斥锁以保护条件变量。
  • 等待条件变量,直到所有工作线程都完成任务。
  • 释放互斥锁。
pthread_barrier_wait(&b);  // 触发工作线程

pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond, &mutex);  // 等待工作线程完成
pthread_mutex_unlock(&mutex);

代码示例

以下是一个代码示例,展示了如何使用条件变量来周期性地触发和等待 pthread 工作线程:

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

#define NTHREADS 4

pthread_cond_t cond;
pthread_mutex_t mutex;
int phase = 0;
int cycle = 0;

// 工作线程函数
void *thread_func(void *x) {
    int tid = ((int *)x)[0];
    while (1) {
        printf("%d: %d %d\n", cycle, tid, phase);

        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);
    }
    return NULL;
}

int main() {
    pthread_t threadids[NTHREADS];      // 存储操作系统线程 ID
    int thread_args[NTHREADS];           // 线程参数
    int rc, i;

    // 初始化条件变量和互斥锁
    pthread_cond_init(&cond, NULL);
    pthread_mutex_init(&mutex, NULL);

    // 创建线程
    for (i = 0; i < NTHREADS; ++i) {
        thread_args[i] = i;
        if ((rc = pthread_create(&threadids[i], NULL, thread_func, (void *)&thread_args[i])) != 0) {
            fprintf(stderr, "无法创建线程 %d\n", i);
            exit(8);
        }
    }

    for (i = 0; i < 10; i++) {              // 执行十次迭代
        printf("cycle %d\n", i);
        phase = (phase + 1) % 3;
        cycle++;

        // 触发工作线程
        pthread_cond_broadcast(&cond);

        // 等待工作线程完成
        pthread_mutex_lock(&mutex);
        pthread_cond_wait(&cond, &mutex);
        pthread_mutex_unlock(&mutex);
    }

    exit(0);
}

结论

通过使用条件变量,我们可以轻松有效地周期性地触发一组 pthread 工作线程并等待它们全部完成。这种方法对于协调多线程任务并确保按预期执行至关重要。

常见问题解答

  1. 什么是条件变量?

答:条件变量是一种线程同步机制,允许一个线程等待特定条件满足,然后继续执行。

  1. 如何使用条件变量协调工作线程?

答:工作线程在完成任务后信号条件变量,而主线程等待条件变量,直到所有工作线程都完成任务。

  1. 为什么我们需要一个互斥锁?

答:互斥锁用于保护对共享数据(条件变量)的访问,防止竞争条件。

  1. 代码示例中的 phasecycle 变量的作用是什么?

答:phasecycle 变量用于跟踪工作线程的当前阶段和执行的迭代次数。

  1. 这个技术有哪些实际应用?

答:这个技术可以应用于各种场景,如并行计算、数据处理和多线程 Web 服务器。