【问题标题】:C pthread: how to activate one thread when a condition is met?C pthread:如何在满足条件时激活一个线程?
【发布时间】:2017-04-02 19:08:21
【问题描述】:

考虑以下程序:

// Compilation: 
// gcc -Wall -Wextra -pedantic -Wno-unused-parameter -O3 test.c -o test -pthread

// Include
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>

// Common variables
sem_t sem;                      // Semaphore
static const int nthr = 4;      // Number of threads
static int n = 0;               // Global counter

// Wait for a given number of seconds
void wait(unsigned int seconds) 
{
    unsigned int limit = time(NULL) + seconds;
    while (time(NULL) < limit);
}

// Function f0
void* f0(void* arg)
{
    while (n < 2); // Here
    // Doing stuff that does no require any access to shared variable
    printf("...doing stuff in f0...\n");
    pthread_exit(NULL);
}

// Function fn
void* fn(void* arg)
{
    sem_wait(&sem);
    wait(1);
    printf("entering fn: n = %d\n", n);
    n++;
    printf("leaving fn: n = %d\n", n);
    wait(1);
    sem_post(&sem);
    pthread_exit(NULL);
}

// Main
int main(int argc, char* argv[])
{
    pthread_t thr[nthr];
    sem_init(&sem, 0, 1);
    pthread_create(&thr[0], NULL, f0, NULL);
    for (int i = 1; i < nthr; ++i) pthread_create(&(thr[i]), NULL, fn, NULL);  
    for (int i = 0; i < nthr; ++i) pthread_join(thr[i], NULL);
    return 0;
}

该程序执行以下操作: thread0 执行 f0,而其他线程正在执行 fn。我希望 f0 等到两个线程增加 n 后再做某事。

当前标记为Here 的行应该这样做,但它不起作用。如何正确地做到这一点(尽可能使用信号量而不是互斥锁)?

【问题讨论】:

  • 你可以使用 pthread_cond_t。
  • 是的,使用 pthread_cond_wait 使用互斥锁。当每个条件都发出信号时,您应该阅读n 并检查是否应该继续。
  • @JensMunk 在本案中如何使用?
  • 看这里。 stackoverflow.com/questions/16522858/… 它解释了如何使用 pthread_cond_wait - 在增加循环计数时保持互斥锁 n。

标签: c multithreading synchronization pthreads semaphore


【解决方案1】:

您可以使用 pthread_cond,如 cmets 中所述:

https://linux.die.net/man/3/pthread_cond_init

IMO cond 有点复杂,所以如果你是从多线程世界开始,我建议首先使用 mutex_lock:

http://pubs.opengroup.org/onlinepubs/009695399/functions/pthread_mutex_lock.html

在这种情况下,您应该使用两个锁,一个用于 f0 函数 (f0_lock),另一个用于读取/写入“n” (var_n_lock) 变量。你的程序应该:

  1. 从 f0_lock 锁定和 var_n_lock 解锁开始。
  2. f0 将等待 f0_lock。
  3. fn 线程会做他们需要做的事情,然后锁定 var_n_lock,将 n 加 1 并检查是否 n == 2,如果是则解锁 f0_lock,最后解锁 var_n_lock。
  4. 当 n == 2 并且运行 f0 的线程将被解锁并继续运行。

我注意到了几件事:在我看来 fn 线程将在 f0 之前完成,如果是这种情况,你应该颠倒你的连接顺序,这将导致一个小的优化。另外,如果你想让你的程序等待一段时间,使用 sleep 或 usleep,它会为你节省大量的 CPU。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-16
    相关资源
    最近更新 更多