Проблемы синхронизации с использованием Pthreads

Я работаю над проектом 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. Постоянно отображается только один, второй - как скрытый, и иногда он мигает только на мгновение. Я предполагаю, что это проблема синхронизации, где я не прав?

1 ответ

Решение

Одна вещь неправильно проходит &i в темы.
когда pthread_create называется, i содержит значение, которое вы хотите. Но к тому времени item_func началось, возможно, изменилось. Таким образом, вполне вероятно, что несколько потоков элементов имеют одинаковое значение для i,

Я не могу сказать, если это все.

Другие вопросы по тегам