2016-11-18 9 views
1

Рассмотрим следующую программу:C pthread: как активировать один поток при выполнении условия?

// 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 должна сделать это, но это не сработает. Как это сделать правильно (используя семафоры вместо мьютексов, когда это возможно)?

+1

Вы можете использовать pthread_cond_t. – sturcotte06

+1

Да, используйте 'pthread_cond_wait', используя мьютекс. Когда каждое условие сигнализируется, вы должны прочитать 'n' и проверить, следует ли продолжить. –

+0

@JensMunk Как использовать его в данном случае? – Vincent

ответ

0

Вы можете использовать pthread_cond, как уже упоминалось в комментариях:

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

IMO конд является немного более сложным, так что если вы начинаете в многопоточном мире, я бы рекомендовал сначала использовать mutex_lock:

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

в этом случае, вы должны использовать два замка, один за функции f0 (f0_lock), а другой для чтения/записи в "п" (var_n_lock) variabl е. Ваша программа должна:

  1. Начать с блокировки f0_lock и разблокировки var_n_lock.
  2. f0 будет ждать f0_lock.
  3. fn threads будет делать то, что им нужно сделать, а затем заблокировать var_n_lock, увеличить n на 1 и проверить, если n == 2, если так разблокировать f0_lock и, наконец, разблокировать var_n_lock.
  4. , когда n == 2, и поток, выполняющийся f0, будет разблокирован и продолжит работу.

Всего лишь пару вещей, которые я заметил: мне кажется, что потоки fn будут закончены до f0, если это так, вы должны инвертировать порядок ваших объединений, это приведет к небольшой оптимизации. Кроме того, если вы хотите, чтобы ваша программа подождала некоторое время, используйте sleep или usleep, это сэкономит вам много CPU.

Надеюсь, это поможет.

 Смежные вопросы

  • Нет связанных вопросов^_^