Мне нужно создать M потоков производителей и N потоков последовательностей на языке c. Программа должна сделать K вставок и K извлечений из очереди. Проблема заключается в том, что когда я выполняю программу, несколько потоков потребителей получают доступ к одному и тому же элементу очереди (и они его извлекают). Таким образом, счетчик "cont" приводит к тому же результату в некоторых извлечениях, и я не понимаю почему, потому что мьютекс и условная переменная, я думаю, правильные.
typedef struct List {
int msg;
struct List* next;
}List;
typedef struct QueueList {
List* list;
List* last;
int cont;
}Queue;
static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
static int K;
static int N;
static int M;
static Queue q;
static void* producer();
static void* consumer();
void push(int num) {
List* l = (List*) malloc(sizeof(List));
l->msg = num;
l->next = NULL;
if(q.list == NULL)
q.last = q.list = l;
else {
q.last->next = l;
q.last = q.last->next;
}
return;
}
void pop() {
List* l;
if(q.list == NULL) {
printf("Head is NULL\n");
return;
}
l = q.list;
q.list = q.list->next;
free(l);
q.cont--;
return;
}
static void* producer() {
for(int i = 0; i < K/M; ++i) {
Pthread_mutex_lock(mtx);
push(i);
printf("Producer(insert): %d\n", q.last->msg);
Pthread_cond_signal(cond);
Pthread_mutex_unlock(mtx);
}
pthread_exit(NULL);
}
static void* consumer() {
while(1) {
Pthread_mutex_lock(mtx);
while(q.list == NULL && q.cont > 0)
Pthread_cond_wait(cond, mtx);
if(q.cont == 0)
break;
printf("Consumer(extract): %d Counter: %d\n", q.list->msg, q.cont);
pop();
Pthread_mutex_unlock(mtx);
}
Pthread_mutex_unlock(mtx);
pthread_exit(NULL);
}
//there are the Pthread function too but they are correct
int main(int argc, char* argv[])
{
if(argc != 4) {
fprintf(stderr, "Usage: %s N M K\n", argv[0]);
exit(1);
}
N = atoi(argv[1]);
M = atoi(argv[2]);
K = atoi(argv[3]);
q.list = q.last = NULL;
q.cont = K - ((K%M)*M);
pthread_t *p, *c;
p = (pthread_t*) malloc(sizeof(pthread_t)*M);
c = (pthread_t*) malloc(sizeof(pthread_t)*N);
int err;
for(int i = 0; i < M; ++i)
if((err = pthread_create(&p[i], NULL, &producer, NULL)) != 0) {
errno = err;
perror("Creating thread");
pthread_exit(&errno);
}
for(int i = 0; i < N; ++i)
if((err = pthread_create(&c[i], NULL, &consumer, NULL)) != 0) {
errno = err;
perror("Creating thread");
pthread_exit(&errno);
}
for(int i = 0; i < M; ++i)
Pthread_join(p[i]);
for(int i = 0; i < N; ++i)
Pthread_join(c[i]);
List* l;
while(q.list != NULL) {
l = q.list;
q.list = q.list->next;
free(l);
}
free(p);
free(c);
}