首页 文章

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

提问于
浏览
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);
}

3 回答

  • 0

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

    #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);
    }
    
  • 0

    使用 N+1 信号量 . 在启动时,线程 i 等待信号量 i . 当它醒来时“转了一圈 and signals semaphore 我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]);
    
  • 3

    每个线程有一个信号量 . 让每个线程 wait 在其信号量上,如果 sem_wait 返回 EINTR 则重试 . 一旦完成它的工作,通过一次只唤醒一个线程,将它 post 放到下一个线程's semaphore. This avoids the 2496255 behaviour of David'的解决方案中 .

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

相关问题