2016-11-18 75 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而其他线程执行fn执行f0。我想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 cond是一个比较复杂一点,所以如果你开始在多线程世界,我会建议先使用的mutex_lock:

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

在这种情况下,你应该用两把锁,你给了F0功能(f0_lock),另一个用于读取/在 “N” 写入(var_n_lock)variabl即您的程序应该:

  1. 以f0_lock locked和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之前完成,如果是这种情况,您应该颠倒连接的顺序,这将导致一个小的优化。另外,如果您希望程序等待一段时间,请使用睡眠或睡眠,这将为您节省大量CPU。

希望这会有所帮助。