2

我正在尝试学习信号量和多线程。我正在使用的示例创建 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);
}
4

3 回答 3

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);
}
于 2012-11-26T04:45:23.737 回答
0

使用N+1信号量。启动时,线程i在 semaphore 上等待i。醒来时它“轮流and signals semaphorei + 1 ”。

主线程产生N, 线程,信号 semaphore 0 并等待 semaphore 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]);
于 2012-11-26T10:09:26.607 回答
0

每个线程有一个信号量。让每个线程都在其信号量上,如果返回wait则重试。一旦它完成了它的工作,就让它到下一个线程的信号量。这通过一次只唤醒一个线程来避免 David 的解决方案的“雷鸣般的羊群”行为。sem_waitEINTRpost

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

于 2012-11-26T10:21:12.050 回答