0

我有一个程序可以创建两个工作线程,如下所示:

void *Producer(void *threadarg){
    while (!terminate_producer){ //do something}
    printf("Producer: finalizing thread\n");
    pthread_exit(NULL);
}

void *Consumer(void *threadarg){
    while (!terminate_consumer){ //do something}
    printf("Consumer: finalizing thread\n");
    pthread_exit(NULL);
}

// Initialize array of the worker threads
void initFuncArray(long result[])
{
    result[0] = (long)&Producer;
    result[1] = (long)&Consumer;
}

// The main method
int main (int argc, char* argv[]){
    long th_funcs[CPUS_NUM];
    initFuncArray(th_funcs);
    // threads data
    pthread_t tid[CPUS_NUM];
    thread_data prod_th_data[CPUS_NUM];
    bool pt = false;
    for (int i=0;i<CPUS_NUM;i++){
        prod_th_data[i].thread_id = i;
        pt = pthread_create(&tid[i], NULL, (void *)th_funcs[i], (void*)&prod_th_data[i]);
        if (pt) return -1;
    }
    sleep(5);
    terminate_producer = true;
    pthread_join (tid[0], NULL);
    **sleep(1);**
    terminate_consumer = true;
    pthread_join (tid[1], NULL);

    // Exiting the main thread
    return 0;
}

我的问题是关于在终止消费者线程之前调用睡眠。如果我没有这个调用,程序会正常终止。但是,如果我有那个睡眠,程序永远不会终止。我看到生产者线程终止的消息,但我没有从消费者线程获得消息。可能是什么问题?

根据建议,我将代码修改如下,但是,即使在中间没有调用 sleep ,问题现在也出现了:

typedef void (*func_type) (void *);
pthread_mutex_t terminate_producer;
pthread_mutex_t terminate_consumer;

void *Producer(void *threadarg){
    while (pthread_mutex_trylock(&terminate_producer)){ //do something}
    printf("Producer: finalizing thread\n");
    pthread_mutex_unlock(&terminate_producer);
    return NULL;
}

void *Consumer(void *threadarg){
    while (pthread_mutex_trylock(&terminate_consumer))
    printf("Consumer: finalizing thread\n");
    pthread_mutex_unlock(&terminate_consumer);
    return NULL;
}

// Initialize array of the worker threads
void initFuncArray(func_type result[])
{
    result[0] = Producer;
    result[1] = Consumer;
}

// The main method
int main (int argc, char* argv[]){
    func_type th_funcs[CPUS_NUM];
    initFuncArray(th_funcs);
    // threads data
    pthread_t tid[CPUS_NUM];
    thread_data prod_th_data[CPUS_NUM];

    // Using mutexes as termination condition
    pthread_mutex_init(&terminate_producer,NULL);
    pthread_mutex_init(&terminate_consumer,NULL);
    pthread_mutex_lock(&terminate_producer);
    pthread_mutex_lock(&terminate_consumer);

    bool pt = false;
    for (int i=0;i<CPUS_NUM;i++){
        prod_th_data[i].thread_id = i;
        pt = pthread_create(&tid[i], NULL, (void *)th_funcs[i], (void*)&prod_th_data[i]);
        if (pt) return -1;
    }
    sleep(5);
    pthread_mutex_unlock(&terminate_producer);
    pthread_join (tid[0], NULL);

    pthread_mutex_unlock(&terminate_consumer);
    pthread_join (tid[1], NULL);

    // Exiting the main thread
    return 0;
}
4

2 回答 2

2

这可能是由于编译器启发式地得出结论(作为一种优化),terminate_consumer 是一个只能在消费者线程中读取的变量,因此它将它“缓存”在寄存器中并且从不读取它。

您可以将 terminate_producer 和 terminate_consumer 的声明更改为:

volatile int terminate_producer;
volatile int terminate_consumer;

.. 然后再试一次?

于 2013-10-16T12:00:01.383 回答
2

Flagterminate_producer代表一个临界区。生产者正在读取它的值,同时主线程正在重写它。应该使用一些同步机制来保护对这个标志的访问,例如互斥锁:

inline stopProducers() {
    /* GET LOCK */
    terminate_producer = 1;
    /* RELEASE LOCK */
}

inline unsigned char shouldProduce() {
    unsigned char terminate = 0;
    /* GET LOCK */
    terminate = terminate_producer;
    /* RELEASE LOCK */
    return !terminate;
}

void *Producer(void *threadarg){
    while (shouldProduce()){ /* do something */ }
    printf("Producer: finalizing thread\n");
    return NULL;  // <-- use return instead of pthread_exit
}

并且main你会打电话stopProducers();而不是重写标志;

于 2013-10-16T11:46:52.757 回答