Продюсер Потребительские Многопоточные проблемы печати
Я написал программу, которая имитирует проблему потребителя производителя, и столкнулся с несколькими проблемами. Это было написано с использованием Win32 API.
Я использую два семафора, полный и пустой, чтобы выполнить подсчет для буфера, в котором хранятся элементы. Существует также мьютекс для контроля доступа к критическому разделу. У меня есть две функции: одна создает элемент на основе простого расчета: нитей * 1000000 + количество, а другая потребляет его.
В буфере 10 пробелов, но, надеюсь, программа сможет работать с разным количеством пробелов и потоков. Поток Producer проходит через буфер, затем запускается снова, пока семафор не подсчитает до 10. Я сталкиваюсь с двумя проблемами, которые, похоже, тоже не могу найти решения, и при этом я не получаю много подробностей в отладчике.
1) Закомментированная часть, которая имеет функцию printf(), прерывает поток каждый раз. Ничто никогда не печатается на консоли. Я попытался использовать только строку без других выводимых переменных. Нет успеха Я нашел документацию, что printf() может столкнуться с проблемами при использовании в многопоточной среде, однако в этом случае он находится в критическом разделе и вылетает с первой попытки. Как я могу распечатать эту информацию на консоли?
2) Когда я удаляю операторы print и запускаю код, потоки все равно каждый раз заканчиваются в разных точках. Я не могу понять, почему. Предполагается, что поток производителя ожидает пустой семафор и мьютекс, помещает элемент, а затем увеличивает счетчик для полного семафора (означающего, что элемент был добавлен). Когда он достигнет 10, он должен остановиться. Поток Consumer ожидает полного семафора и мьютекса, удаляет элемент и увеличивает количество пустых семафоров. Есть ли что-то в том, как я написал это, что вызывает выход этих потоков?
Вот что я получаю:
Программа '[5348] OperatingSystem.exe' вышла с кодом 0 (0x0).
#include<stdio.h>
#include<windows.h>
#include<ctype.h>
#include<tchar.h>
#include<strsafe.h>
#include<conio.h>
#include<time.h>
#define threads 1
#define MAX 10
typedef struct objects {
HANDLE empty;
HANDLE full;
HANDLE mutex;
int buffer[10];
};
struct objects data;
DWORD WINAPI Producers(LPVOID lpParam){
int count = 0;
int item;
while (TRUE){
if (data.buffer[count] == 0){
WaitForSingleObject(data.empty, INFINITE);
WaitForSingleObject(data.mutex, INFINITE);
item = threads * 1000000 + count;
data.buffer[count] = item;
//printf("Producer has produced: %d", item);
ReleaseMutex(data.mutex);
ReleaseSemaphore(data.full, 1, NULL);
}
count++;
if (count == 10){ count = 0; }
};
}
DWORD WINAPI Consumers(LPVOID lpParam){
int count = 0;
while (TRUE){
if (data.buffer[count] != 0){
WaitForSingleObject(data.full, INFINITE);
WaitForSingleObject(data.mutex, INFINITE);
//printf("Consumer has consummed: %d", data.buffer[count]);
data.buffer[count] = 0;
ReleaseMutex(data.mutex);
ReleaseSemaphore(data.empty, 1, NULL);
}
count++;
if (count == 10){ count = 0; }
};
}
int main(int argc, char *argv[]) {
struct objects data;
LONG initialCount = 0;
LONG maxCount = 10;
data.empty = CreateSemaphore(NULL, maxCount, maxCount, NULL);
data.full = CreateSemaphore(NULL, initialCount, maxCount, NULL);
data.mutex = CreateMutex(NULL, FALSE, NULL);
DWORD ConsumerId[threads];
HANDLE ConsumerThread[threads];
DWORD ProducerId[threads];
HANDLE ProducerThread[threads];
for (int i = 0; i < threads; i++){
ProducerThread[i] = CreateThread(
NULL,
0,
Producers,
NULL,
0,
&ProducerId[i]);
ConsumerThread[i] = CreateThread(
NULL,
0,
Consumers,
NULL,
0,
&ConsumerId[i]);
}
}