gpt4 book ai didi

c - C 中的缓冲区互斥量和条件变量

转载 作者:行者123 更新时间:2023-12-03 12:58:38 25 4
gpt4 key购买 nike

我刚刚开始用 C 编写多线程,并没有完全了解如何实现它。我正在编写一个读取输入文件并将其放入缓冲区结构数组的代码。当缓冲区没有更多可用空间时,request_t被阻塞等待可用空间。它由线程控制 Lift_R .其他线程电梯1-3操作lift()并将缓冲区中的内容写入输出文件,具体取决于 int sec 的数量. secsize并通过命令行给定值。这将为请求释放空间以继续读取输入。

有人可以帮助我如何正确实现这些功能。我知道还有其他与此相关的问题,但我希望我的代码满足特定条件。

(注意:lift 在 FIFO 中运行,线程使用互斥)

这是我到目前为止所写的,我还没有实现任何等待条件或 FIFO,我目前专注于写入文件和调试,很快就会等待和发出信号。

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "list.h"
pthread_cond_t cond1 = PTHREAD_COND_INITIALIZER; //declare thread conditions
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; //declare mutex
int sec; //time required by each lift to serve a request
int size; //buffer size
buffer_t A[];
write_t write;
void *lift(void *vargp)

{
pthread_mutex_lock(&lock);
FILE* out;
out = fopen("sim_output.txt", "w");
//gather information to print
if (write.p == NULL) //only for when system begins
{
write.p = A[1].from;
}
write.rf = A[1].from;
write.rt = A[1].to;
write.m = (write.p - A[1].from) + (A[1].to - A[1].from);
if (write.total_r == NULL) //for when the system first begins
{
write.total_r = 0;
}
else
{
write.total_r++;
}
if (write.total_m == NULL)
{
write.total_m = write.m;
}
else
{
write.total_m = write.total_m + write.m;
}
write.c = A[1].to;
//Now write the information
fprintf(out, "Previous position: Floor %d\n", write.p);
fprintf(out, "Request: Floor %d to Floor %d\n", write.rf, write.rt);
fprintf(out, "Detail operations:\n");
fprintf(out, " Go from Floor %d to Floor %d\n", write.p, write.rf);
fprintf(out, " Go from Floor %d to Floor %d\n", write.rf, write.rt);
fprintf(out, " #movement for this request: %d\n", write.m);
fprintf(out, " #request: %d\n", write.total_r);
fprintf(out, " Total #movement: %d\n", write.total_m);
fprintf(out, "Current Position: Floor %d\n", write.c);
write.p = write.c; //for next statement
pthread_mutex_unlock(&lock);
return NULL;
}


void *request_t(void *vargp)
{
pthread_mutex_lock(&lock); //Now only request can operate
FILE* f;
FILE* f2;
f = fopen("sim_input.txt", "r");
if (f == NULL)
{
printf("input file empty\n");
exit(EXIT_FAILURE);
}
f2 = fopen("sim_output.txt", "w");

int i = 0;
for (i; i < size; i++)
{
//read the input line by line and into the buffer
fscanf(f, "%d %d", &A[i].from, &A[i].to);\
//Print buffer information to sim_output
fprintf(f2, "----------------------------\n");
fprintf(f2, "New Lift Request from Floor %d to Floor %d \n", A[i].from, A[i].to);
fprintf(f2, "Request No %d \n", i);
fprintf(f2, "----------------------------\n");
}
printf("Buffer is full");
fclose(f);
fclose(f2);
pthread_mutex_unlock(&lock);
return NULL;
}


void main(int argc, char *argv[]) // to avoid segmentation fault
{
size = atoi(argv[0]);
if (!(size >= 1))
{
printf("buffer size too small\n");
exit(0);
}
else
{
A[size].from = NULL;
A[size].to = NULL;
}
sec = atoi(argv[1]);
pthread_t Lift_R, lift_1, lift_2, lift_3;

pthread_create(&Lift_R, NULL, request_t, NULL);

pthread_join(Lift_R, NULL);

pthread_create(&lift_1, NULL, lift, NULL);

pthread_join(lift_1, NULL);

pthread_create(&lift_2, NULL, lift, NULL);

pthread_join(lift_2, NULL);

pthread_create(&lift_3, NULL, lift, NULL);

pthread_join(lift_3, NULL);

}

这是结构文件:
#include <stdbool.h>

typedef struct Buffer
{
int from;
int to;
}buffer_t; //buffer arrary to store from and to values from sim_input

typedef struct Output
{
int l; //lift number
int p; //previous floor
int rf; //request from
int rt; //request to
int total_m; //total movement
int c; // current position
int m; //movement
int total_r; //total requests made
}write_t;

最佳答案

在阅读您的代码和问题之间,我看到了一个很大的概念差距。代码中存在一些技术问题(例如,您永远不会关闭);和一个难以遵循的顺序。

所以,这个模式:

  pthread_create(&x, ?, func, arg);
pthread_join(x, ...);

可以替换为:
  func(arg);

所以,你根本就不是多线程的;就好像:
void main(int argc, char *argv[]) // to avoid segmentation fault
{
size = atoi(argv[0]);
if (!(size >= 1))
{
printf("buffer size too small\n");
exit(0);
}
else
{
A[size].from = NULL;
A[size].to = NULL;
}
sec = atoi(argv[1]);

request_t(0);
lift(0);
lift(0);
lift(0);
}

并且,知道这一点,我希望您能看到以下内容的徒劳:
pthread_mutex_lock(&lock);
....
pthread_mutex_unlock(&lock);

所以,从重新思考你在做什么开始。听起来您有一个电梯设备需要接收入站请求,可能对它们进行排序,然后处理它们。可能是“永远”。

这可能意味着一个有序的队列;然而,一个不是按普通标准排序的。电梯在两个方向上穿过建筑物,但意味着尽量减少方向的变化。这涉及使用顺序 ( >, < ) 和当前方向遍历队列。
您可能希望 request 简单地评估提升图,并确定在何处插入新请求。
电梯图将是电梯下一步去向的单向列表。并且,也许有一条规则,即列表仅在停在给定楼层时才查阅其列表。

因此,请求可以锁定图形,更改它以反射(reflect)新请求,然后解锁它。

电梯可以简单地:
  while (!Lift_is_decommissioned) {
pthread_mutex_lock(&glock);
Destination = RemoveHead(&graph);
pthread_mutex_unlock(&glock);
GoTo(Destination);
}

请求可以是:
  pthread_mutex_lock(&glock);

NewDestination = NewEvent.floorpressed;
NewDirection = NewEvent.floorpressed > NewEvent.curfloor ? Up : Down;
i = FindInsertion(&graph, NewDestination, NewDirection);
InsertAt(&graph, i, NewDestination);

pthread_mutex_unlock(&glock);

从电梯内按“转到楼层”按钮和从电梯外按“我现在要电梯”之间没有区别,这可能有点令人惊讶。

但是,通过这种分离,您可以让电梯简单地遵循上面的方法,按钮的处理程序调用上面的其他伪代码。

FindInsertion() 可能有点麻烦....

关于c - C 中的缓冲区互斥量和条件变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61314021/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com