【问题标题】:Using parameters with threads在线程中使用参数
【发布时间】:2018-09-05 07:32:17
【问题描述】:

我正在使用 linux pthreads 库来尝试线程功能,下面的代码在屏幕上为每个线程打印 5 条消息,每个线程等待轮到显示使用信号量控制的消息,在 Windows 中它运行良好,但是在 linux 中,线程不会等待轮到它们,我已经研究了所有正在唱歌的东西,但我无法解决这个问题。我的推断是我在参数结构上做错了

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

typedef struct param{
  int id;
  pthread_mutex_t lock;
  sem_t semaforo;
}valores_t;

void * olamundo(void* args){
  valores_t* p = args;
  sem_wait(&p->semaforo);
  for (size_t i = 0; i < 5; i++) {
    printf("Hello from thread %d\n", p->id);
  }
  sem_post(&p->semaforo);
}

sem_t semaforo;

int main(int argc, char const *argv[]) {
  /* code */

  if(sem_init(&semaforo,0,1)){//valor inicial do semaforo começa por 1
    printf("Error\n");
  }

  valores_t p[2];
  pthread_t threads[2];

    p[0].id = 1;
    p[0].semaforo = semaforo;

    p[1].id = 2;
    p[1].semaforo = semaforo;

  for(int i = 0; i < 2; i++){
    if(pthread_create(&(threads[i]), NULL, &olamundo, &p[i]) == -1){
      printf("Error\n");
    }
  }

  for(int i = 0; i < 2; i++){
        if(pthread_join(threads[i], NULL)){
      printf("Error\n");
    }
    }
    sem_destroy (&semaforo);
  return 0;
}

【问题讨论】:

  • 似乎你应该在循环之前sem_wait,在循环之后sem_post
  • 没有任何改变
  • 我已经有一段时间没有编写任何直接调用 pthreads API 的代码了,但我对 p[0].semaforo=semaforo;p[1].semaforo=semaforo;The documentation 的分配持怀疑态度@ 987654327@ 数据type 没有明确承诺这些分配会起作用。如果没有任何这样的承诺,我会假设 semaphore_t 值可能是一个结构,并且复制一个会创建一个新的、不同的信号量或无效的信号量。
  • 一般来说:用英文编码可能会让我们更容易为您提供帮助

标签: c multithreading pthreads


【解决方案1】:

我已经在 ubuntu 14.04(gcc v4.8) 上测试了你的代码,它按预期工作,所以我猜测这是编译器的问题。正如 james large 的评论所暗示的那样,您的编译器可能会在复制时创建信号量的新副本 - 您可以使用任何调试工具测试此理论,以验证信号量确实相同\不同对象。

但更好的解决方案是将其作为指针传递,以确保它不依赖于编译器:

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

typedef struct param{
    int id;
    pthread_mutex_t lock;
    sem_t *semaforo; //Dagan: change to a pointer to a semaphore
}valores_t;

void * olamundo(void* args){
    valores_t* p = args;
    sem_wait(*(&p->semaforo)); //Dagan: use the semaphore pointer
    for (size_t i = 0; i < 25; i++) {
        printf("Ola mundo da thread %d\n", p->id);
    }
    sem_post(*(&p->semaforo)); //Dagan: use the semaphore pointer
}

sem_t semaforo;

int main(int argc, char const *argv[]) {
    /* code */

    if(sem_init(&semaforo,0,1)){//valor inicial do semaforo começa por 1
        printf("Erro ao iniciar o semaforo\n");
    }

    valores_t p[2];
    pthread_t threads[2];

    p[0].id = 1;
    p[0].semaforo = &semaforo; //Dagan: pass the address of the semaphore

    p[1].id = 2;
    p[1].semaforo = &semaforo; //Dagan: pass the address of the semaphore

    for(int i = 0; i < 2; i++){//inicia as funcoes das threads
        if(pthread_create(&(threads[i]), NULL, &olamundo, &p[i]) == -1){
            printf("Erro ao inicializar a thread\n");
        }
    }

    for(int i = 0; i < 2; i++){
        if(pthread_join(threads[i], NULL)){
            printf("Erro ao sincronizar a thread\n");
        }
    }
    sem_destroy (&semaforo);
    return 0;
}

在同一个编译器上测试和工作 - 我认为这是一个更安全的解决方案 希望这会有所帮助

【讨论】:

  • 感谢@Dagan!我已经使用 gcc 5.4.0 在 ubuntu 17.04 上进行了测试,并且按预期工作!
猜你喜欢
  • 2021-01-11
  • 2011-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 1970-01-01
  • 2021-03-05
相关资源
最近更新 更多