C ++使用信号量而不是繁忙的等待

时间:2012-11-26 04:03:27

标签: c++ multithreading pthreads posix semaphore

我正在尝试学习信号量和多线程。我正在使用的示例创建1到t个线程,每个线程指向下一个,最后一个线程指向第一个线程。该程序允许每个线程顺序转动,直到所有线程转了n圈。那是程序结束的时候。唯一的问题是在tFunc函数中,我正忙着等到它是一个特定的线程。我想知道如何使用信号量,以便让所有线程进入休眠状态并仅在轮到执行时唤醒线程以提高效率。

int turn = 1;
int counter = 0;
int t, n;

struct tData {
        int me;
        int next;
};

void *tFunc(void *arg) {
        struct tData *data;
        data = (struct tData *) arg;
        for (int i = 0; i < n; i++) {
            while (turn != data->me) {
        }
        counter++;
        turn = data->next;
    }
}

int main (int argc, char *argv[]) {
    t = atoi(argv[1]);
    n = atoi(argv[2]);
    struct tData td[t];
    pthread_t threads[t];
    int rc;

    for (int i = 1; i <= t; i++) {
        if (i == t) {
            td[i].me = i;
            td[i].next = 1;
        }
        else {
            td[i].me = i;
            td[i].next = i + 1;
        }
        rc = pthread_create(&threads[i], NULL, tFunc, (void *)&td[i]);
        if (rc) {
            cout << "Error: Unable to create thread, " << rc << endl;
            exit(-1);
        }
    }
    for (int i = 1; i <= t; i++) {
        pthread_join(threads[i], NULL);
    }
    pthread_exit(NULL);
}

3 个答案:

答案 0 :(得分:3)

使用互斥锁和条件变量。这是一个有效的例子:

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

int turn = 1;
int counter = 0;
int t, n;

struct tData {
        int me;
        int next;
};

pthread_mutex_t mutex;
pthread_cond_t cond;

void *tFunc(void *arg)
{
    struct tData *data;
    data = (struct tData *) arg;
    pthread_mutex_lock(&mutex);
    for (int i = 0; i < n; i++)
    {
        while (turn != data->me)
            pthread_cond_wait(&cond, &mutex);
        counter++;
        turn = data->next;
        printf("%d goes (turn %d of %d), %d next\n", data->me, i+1, n, turn);
        pthread_cond_broadcast(&cond);
    }
    pthread_mutex_unlock(&mutex);
}

int main (int argc, char *argv[]) {
    t = atoi(argv[1]);
    n = atoi(argv[2]);
    struct tData td[t + 1];
    pthread_t threads[t + 1];
    int rc;

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

    for (int i = 1; i <= t; i++)
    {
        td[i].me = i;
        if (i == t)
            td[i].next = 1;
        else
            td[i].next = i + 1;

        rc = pthread_create(&threads[i], NULL, tFunc, (void *)&td[i]);
        if (rc)
        {
            printf("Error: Unable to create thread: %d\n", rc);
            exit(-1);
        }
    }
    void *ret;
    for (int i = 1; i <= t; i++)
        pthread_join(threads[i], &ret);
}

答案 1 :(得分:0)

使用N+1信号量。启动时,线程i等待信号量i。当它被唤醒时“需要转弯and signals semaphore i + 1。”

主线程产生N,线程,信号信号0并等待信号量N

伪代码:

sem s[N+1];

thread_proc (i):
  repeat N:
      wait (s [i])
      do_work ()
      signal (s [i+1])

main():
  for i in 0 .. N:
    spawn (thread_proc, i)

  repeat N:    
      signal (s [0]);
      wait (s [N]);

答案 2 :(得分:0)

每个线程都有一个信号量。在其信号量上放置每个线程wait,如果sem_wait返回EINTR则重试。完成它的工作后,将它post放到下一个线程的信号量上。这通过一次只唤醒一个线程来避免大卫解决方案的“雷鸣般的群体”行为。

另请注意,由于您的信号量永远不会超过1,因此您可以使用pthread_mutex_t