【问题标题】:(C, pthreads) Let multiple threads synchronize and continue together(C, pthreads) 让多个线程同步并一起继续
【发布时间】:2017-11-20 09:46:35
【问题描述】:

我有一个由多个线程组成的程序。 这些线程必须在某个时刻同步,一起继续,完成不同长度的工作,然后再次同步。

这是我的意思的例子:

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

#define NUM_THREADS 10

void* thread(void* idp);

int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;

int main(int args, char **argv)
{
    pthread_mutex_t mutex_var;
    pthread_cond_t cond_var;

    mutex = &mutex_var;
    cond = &cond_var;

    pthread_mutex_init(mutex, NULL); 
    pthread_cond_init(cond, NULL);

    pthread_t threads[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++)
    {
        printf("Creating Thread %d....\n", i);

        int* id = malloc(sizeof(int));
        *id = i;

        if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
        {
            perror("Error while creating the threads");
            exit(1);
        }
    }

    for (int i = 0; i < NUM_THREADS; i++) 
    {
        pthread_join(threads[i], NULL);
    }

    return 0;
}


void* thread(void* idp)
{   
    int* id = (int*) idp;

    while (1)
    {
        sleep(*id+2); // Thread work

        pthread_mutex_lock(mutex);
            threads_running++;
        pthread_mutex_unlock(mutex);
        pthread_cond_broadcast(cond);

        printf("Thread %d WAIT\n", *id);
        fflush(stdout);

        // Let threads synchronize

        pthread_mutex_lock(mutex);
            while(threads_running != NUM_THREADS)
            {
                pthread_cond_wait(cond, mutex);
            }
        pthread_mutex_unlock(mutex);    

        printf("Thread %d WAKEUP\n", *id);
        fflush(stdout);

        // and continue

        pthread_mutex_lock(mutex);
            threads_running--;
        pthread_mutex_unlock(mutex);
    }
}

发生的事情是,一些(通常是#9 和其他一两个)到达Thread %d WAKEUP,但在其他人唤醒之前threads_running 已经小于NUM_THREADS

如何同步多个线程,以便它们一起继续? 我在理解对变量的并行访问时遇到了一些麻烦。

【问题讨论】:

标签: c multithreading synchronization pthreads


【解决方案1】:

我建议使用 pthread_cond_signal() 而不是 pthread_cond_broadcast(cond); 所以 while 循环退出的代码流如下所示。

        pthread_mutex_lock(mutex);
        while(threads_running != 0 && threads_running != NUM_THREADS)
        {
            pthread_cond_wait(cond, mutex);
        }
    pthread_cond_signal(cond);

所以最终的代码是这样的:

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

#define NUM_THREADS 10

void* thread(void* idp);

int threads_running = 0;
pthread_mutex_t* mutex;
pthread_cond_t* cond;

int main(int args, char **argv)
{
    pthread_mutex_t mutex_var;
    pthread_cond_t cond_var;

    mutex = &mutex_var;
    cond = &cond_var;

    pthread_mutex_init(mutex, NULL); 
    pthread_cond_init(cond, NULL);

    pthread_t threads[NUM_THREADS];

    for (int i = 0; i < NUM_THREADS; i++)
    {
        printf("Creating Thread %d....\n", i);

        int* id = malloc(sizeof(int));
        *id = i;

        if(0 != pthread_create(&threads[i], NULL, thread, (void *) id))
        {
            perror("Error while creating the threads");
            exit(1);
        }
    }

    for (int i = 0; i < NUM_THREADS; i++) 
    {
        pthread_join(threads[i], NULL);
    }

    return 0;
}


void* thread(void* idp)
{   
    int* id = (int*) idp;

    while (1)
    {
        sleep(*id+2); // Thread work

        pthread_mutex_lock(mutex);
            threads_running++;
        pthread_mutex_unlock(mutex);

        printf("Thread %d WAIT\n", *id);
        fflush(stdout);

        // Let threads synchronize

        pthread_mutex_lock(mutex);
            while(threads_running != 0 && threads_running != NUM_THREADS)
            {
                pthread_cond_wait(cond, mutex);
            }
        pthread_cond_signal(cond);

        pthread_mutex_unlock(mutex);    

        printf("Thread %d WAKEUP\n", *id);
        fflush(stdout);

        // and continue
        pthread_mutex_lock(mutex);
            threads_running = 0;
        pthread_mutex_unlock(mutex);
    }
}

【讨论】:

    【解决方案2】:

    几秒钟后我找到了答案:

    1. while(threads_running != NUM_THREADS) 更改为while(threads_running != 0 &amp;&amp; threads_running != NUM_THREADS)

    2. threads_running--;更改为threads_running = 0;

    现在它可以完美运行了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-03
      • 1970-01-01
      • 2021-07-10
      • 2011-12-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多