我正在开发一个C项目,它包含一个使用ncurses和pthread库的简单游戏。不得不说我还在学习,我已经陷入了一些同步问题,使用互斥锁和信号量。 我将尝试解释它应该如何工作,因为它可能会有所帮助。它遵循生产者/消费者的想法。使用结构(包含适当的值,如坐标等)生成一堆线程。这些结构在屏幕上由角色表示,并在每次互动时移动。所有这些信息都存储在缓冲区中。 一个线程必须通过访问缓冲区,读取坐标以及在屏幕上打印项目来管理和协调这些项目。 我主要是为了让它更容易阅读,这是代码:
#include <stdio.h>
#include <time.h>
#include <curses.h>
#include <pthread.h>
#include <stdlib.h>
#include <signal.h>
#include <semaphore.h>
#include <unistd.h>
#define STEP 1 //value of the moving
#define M 2 // number of items
#define BUFFER_DIM 100000
void * control_func(void * arg);
void * item_func(void * arg);
typedef struct pos{//structure for the communication
char c; // type of item
int x; // x coord
int y; // y coord
int p; // object pos
int pid; // pid of process
} pos;
typedef struct argomenti{ //structure to pass arguments
int x; //x position
int y; //y position
int i; //index
} args;
//buffer and semaphores initializations
pos buffer[BUFFER_DIM];
int IN = 0; // occupied positions of the buffer
int OUT = 0; // avariable position of the buffer
sem_t presents, avariables; // variabili che indicano il valore del semaforo, ovvero la presenza o meno di job disponibili
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // mutex to avoid race conditions
main(){
initscr();
noecho();
curs_set(0);
srand(time(NULL));
pthread_t item_id[M], control_id;
int i;
sem_init(&avariables, 0, BUFFER_DIM); //initialize semaphores
sem_init(&presents, 0, 0);
//start threads
for(i=0;i<M;i++){
pthread_create(&item_id[i], NULL, &item_func, &i);
}
pthread_create(&control_id, NULL, &control_func, NULL);
pthread_join(control_id, NULL);
endwin();
return(0);
}
void * item_func(void * arg){
pos pos_item;
int i = *((int *)arg);
int dx=STEP;
pos_item.c='$';
pos_item.p=i;
pos_item.pid=pthread_self();
pos_item.y=1;
pos_item.x=rand()%80;
sem_wait(&avariables);
pthread_mutex_lock(&mutex);
buffer[IN] = pos_item;
IN=(IN+1)%BUFFER_DIM;
sem_post(&presents); // increment of the semaphore
pthread_mutex_unlock(&mutex);
while(1){//code for the changes of the coords
if(pos_item.x==80){//80 are the columns
dx=-STEP;
pos_item.x += dx;
pos_item.y++;
}else if(pos_item.x==0){
dx=STEP;
pos_item.x += dx;
pos_item.y++;
}else
pos_item.x += dx;
sem_wait(&avariables);
pthread_mutex_lock(&mutex);
buffer[IN] = pos_item;
IN=(IN+1)%BUFFER_DIM;
sem_post(&presents); // increment of the semaphore
pthread_mutex_unlock(&mutex);
usleep(100000);}
}
void * control_func(void * arg)
{
pos item[M], read_value;
int i,j;
for(i=0;i<M;i++){
item[i].x=-1;
}
do{
sem_wait(&presents);
pthread_mutex_lock(&mutex);
read_value = buffer[OUT];
OUT=(OUT+1)%BUFFER_DIM;
sem_post(&avariables); // increment of the semaphore
pthread_mutex_unlock(&mutex);
switch(read_value.c) {
case '$':
if(item[read_value.p].x>=0)
mvaddch(item[read_value.p].y,item[read_value.p].x,' '); //delete the old position
item[read_value.p]=read_value; //refresh the position
mvaddch(item[read_value.p].y,item[read_value.p].x,item[read_value.p].c); //print the item
break;
}
refresh();
}while(1);
}
它编译时没有警告(-lncurses -lpthread),但不知怎的,它无法正常工作。项目的数量设置为2.只有一个是永久显示的,另一个是大多数时候隐藏的,有时它只是瞬间闪烁。 我认为这是一个同步问题,我错在哪里?
答案 0 :(得分:2)
有一件事是将&i
传递给线程
调用pthread_create
时,i
包含您想要的值。但到item_func
开始时,它可能已经改变了。因此,多个项目线程可能具有i
的相同值。
我不知道是不是全部。