C++ C++;使用信号灯而不是忙着等待

C++ C++;使用信号灯而不是忙着等待,c++,multithreading,pthreads,posix,semaphore,C++,Multithreading,Pthreads,Posix,Semaphore,我试图学习信号量和多线程。我正在使用的示例创建1到t个线程,每个线程指向下一个线程,最后一个线程指向第一个线程。此程序允许每个线程依次执行一次循环,直到所有线程执行n次循环。这就是节目结束的时候。唯一的问题是在tFunc函数中,我正忙着等待,直到轮到特定线程。我想知道如何使用信号量使所有线程进入睡眠状态,只有在轮到线程执行时才唤醒线程以提高效率 int turn = 1; int counter = 0; int t, n; struct tData { int me;

我试图学习信号量和多线程。我正在使用的示例创建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);
}
int-turn=1;
int计数器=0;
int t,n;
结构数据{
给我指点;
int-next;
};
void*tFunc(void*arg){
结构tData*数据;
数据=(结构tData*)参数;
对于(int i=0;i我){
}
计数器++;
turn=数据->下一步;
}
}
int main(int argc,char*argv[]){
t=atoi(argv[1]);
n=atoi(argv[2]);
结构tdatatd[t];
pthread_t线程[t];
int rc;

for(int i=1;i使用互斥量和条件变量。下面是一个工作示例:

#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;
int计数器=0;
int t,n;
结构数据{
给我指点;
int-next;
};
pthread_mutex_t mutex;
pthread_cond_t cond;
void*tFunc(void*arg)
{
结构tData*数据;
数据=(结构tData*)参数;
pthread_mutex_lock(&mutex);
对于(int i=0;i我)
pthread_cond_wait(&cond,&mutex);
计数器++;
turn=数据->下一步;
printf(“%d开始(第%d轮,共%d轮),%d下一轮,\n”,数据->我,我+1,n,轮);
pthread_cond_广播(&cond);
}
pthread_mutex_unlock(&mutex);
}
int main(int argc,char*argv[]){
t=atoi(argv[1]);
n=atoi(argv[2]);
结构tdatatd[t+1];
pthread_t线程[t+1];
int rc;
pthread_mutex_init(&mutex,NULL);
pthread_cond_init(&cond,NULL);

对于(inti=1;i使用
N+1
信号量。在启动时,线程
i
等待信号量
i
。当它醒来时,“轮流
并发出信号量
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]);

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


还注意到,由于信号量永远不会有大于1的值,因此可以使用<代码> pthRead MutExtUT <代码>。

<代码>(回合!=数据-> me){} /COD> >?C++数组是零基-<代码>(int i=1;i它只是循环直到轮到它。我在网上只找到了简单的信号量示例,并尝试实现它…但我认为我需要多个信号量,现在我不知道如何实现它。嗯…我刚刚意识到它确实超出了界限,但出于某种原因,它仍然编译并运行良好…拿一个例子来说看看