【问题标题】:semaphores not working correctly信号量无法正常工作
【发布时间】:2017-10-05 01:05:12
【问题描述】:

我一直在尝试编写一个程序,在该程序中我使用线程和信号量来模拟最短优先作业算法。当主线程告诉他这样做时,每个线程都负责打印其 id。主线程(主线程)将控制这些作业的时间打印在屏幕上。以下是我想出的,但我似乎做错了我还无法弄清楚的事情。我设法让它相应地打印出作业,但它总是有 2 个在 10 个中丢失。文件格式是“id(char)到达(int)burst(int)”。所以我在这里迫切需要帮助,因为我有尝试了很多事情,但结果总是和我几个小时一样。

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#define MAX 10

sem_t childs[MAX];
sem_t master;

int jobdone = 0;

typedef struct job
{
  int burst, arrival, wait_time, turn_around, executed, done;
  char id;
} JOB;

JOB jobs[MAX];

void ShortestFirstJob()
{

  int i, j;
  char id;
  int burst, arrival, wait_time, turn_around, done;
  for (i = 0; i < MAX; i++)
  {
    for (j = 0; j < MAX - 1; j++)
    {
      if (jobs[j].arrival > jobs[j + 1].arrival)
      {
        id = jobs[j].id;
        done = jobs[j].done;
        burst = jobs[j].burst;
        arrival = jobs[j].arrival;
        wait_time = jobs[j].wait_time;
        turn_around = jobs[j].turn_around;
        jobs[j].id = jobs[j + 1].id;
        jobs[j].burst = jobs[j + 1].burst;
        jobs[j].wait_time = jobs[j + 1].wait_time;
        jobs[j].arrival = jobs[j + 1].arrival;
        jobs[j].turn_around = jobs[j + 1].turn_around;
        jobs[j].done = jobs[j + 1].done;
        jobs[j + 1].id = id;
        jobs[j + 1].burst = burst;
        jobs[j + 1].arrival = arrival;
        jobs[j + 1].wait_time = wait_time;
        jobs[j + 1].turn_around = turn_around;
        jobs[j + 1].done = done;

      }
    }
  }
  printf("SORT \n");
  for (j = 0; j < MAX; j++)
  {
    printf("%c %d %d\n", jobs[j].id, jobs[j].arrival, jobs[j].burst);
  }

}

void* PrintJob(void *params)
{

  char id = *((char*) params);

  int i, j, k;
  for (i = 0; i < MAX; i++)
  {
    if (id == jobs[i].id)
      break;
  }

  for (k = 0; k < jobs[i].burst; k++)
  {

    sem_wait(&childs[i]);
    printf("%c", id);
    fflush(stdout);
    jobs[i].executed += 1;

    for (j = 0; j < MAX; j++)
    {
      if ((i != j) && (jobs[j].arrival > 0))
      {
        jobs[j].arrival -= 1;
        jobs[j].wait_time += 1;
      }
    }

    sem_post(&master);
  }

  jobs[i].done = 1;
  jobdone++;

}
int main()
{

  pthread_t threadIds[MAX];
  char threadsIdx;
  int result;
  int i = 0;
  int j;
  int index[MAX];

  FILE* fp = fopen("joblist1.txt", "r");

  for (j = 0; j < MAX; j++)
  {
    sem_init(&childs[j], 0, 0);
  }
  sem_init(&master, 0, 1);

  char id;
  int arrival, burst;
  while (fscanf(fp, "%c %d %d\n", &id, &arrival, &burst) != EOF)
  {

    jobs[i].id = id;
    jobs[i].arrival = arrival;
    jobs[i].burst = burst;
    jobs[i].wait_time = 0;
    jobs[i].turn_around = 0;
    jobs[i].executed = 0;
    jobs[i].done = 0;

    i++;
  }

  for (j = 0; j < MAX; j++)
  {
    printf("%c %d %d\n", jobs[j].id, jobs[j].arrival, jobs[j].burst);
  }

  ShortestFirstJob();

  for (i = 0; i < MAX; i++)
  {

    if (pthread_create(&threadIds[i], NULL, PrintJob, &jobs[i].id) != 0)
    {
      perror("thread create");
      exit(1);
    }
  }

  int k, c = 0;
  int min = 0;
  int in = 0;
  int value, flag = 0;
  while (jobdone < MAX)
  {

    k = 0;
    c = 0;

    sem_wait(&master);
    for (j = 0; j < MAX; j++)
    {
      if ((jobs[j].arrival == 0) && (jobs[j].done != 1))
      {
        index[k++] = j;
        c++;

      }
    }

    if (c == 1)
    {

      sem_post(&childs[index[0]]);

    }
    else if (c > 1)
    {

      min = jobs[index[0]].burst;
      for (j = 1; j < k; j++)
      {
        if (jobs[index[j]].burst <= min)
        {
          min = jobs[index[j]].burst;
          in = index[j];

        }
      }

      sem_post(&childs[in]);

    }

  }

  for (i = 0; i < MAX; i++)
  {
    pthread_join(threadIds[i], NULL );
  }

  return 0;

}

【问题讨论】:

    标签: c multithreading pthreads threadpool semaphore


    【解决方案1】:

    我对你的一些计算不是很了解,但我发现了两个问题。

    首先,在函数PrintJob()中,你应该在发布主信号之前设置jobs[i].done = 1;,因为主线程评估jobs[i].done来决定它会唤醒哪个线程。

    所以PrintJob()函数的正确代码应该是:

    void* PrintJob(void *params) {
    
      char id = *((char*) params);
    
      int i, j, k;
      for (i = 0; i < MAX; i++) {
        if (id == jobs[i].id) break;
      }
    
      for (k = 0; k < jobs[i].burst; k++) {
        sem_wait(&childs[i]);
        printf("%c", id);
        fflush(stdout);
        jobs[i].executed += 1;
    
        for (j = 0; j < MAX; j++)
        {
          if ((i != j) && (jobs[j].arrival > 0))
          {
            jobs[j].arrival -= 1;
            jobs[j].wait_time += 1;
          }
        }
    
        /////////////////////////////
        // Here:
        if(k == (jobs[i].burst - 1))
          jobs[i].done = 1;
          jobdone++;
        }
        /////////////////////////////
    
        sem_post(&master);
      }
    }
    

    第二个问题在主线程中。我不知道究竟是什么问题,但是当我测试你的程序时,问题就在这里,主线程试图唤醒一个将jobs[index[j]].done 设置为1 的已完成线程。我不确定这是主要问题,但是当jobs[index[0]].burst 是最小值时,您似乎忘记给in 赋值。所以正确的代码应该是:

    else if (c > 1) {
    
      min = jobs[index[0]].burst;
    
      // Here:
      in = index[0];
    
      for (j = 1; j < k; j++)
      {
        if (jobs[index[j]].burst <= min)
        {
          min = jobs[index[j]].burst;
          in = index[j];
        }
      }
    
      sem_post(&childs[in]);
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-02
      • 1970-01-01
      • 1970-01-01
      • 2013-07-09
      • 1970-01-01
      相关资源
      最近更新 更多