我编写了一个模拟生产者消费者问题的程序,我遇到了几个问题。这是使用Win32 API编写的。
我使用两个信号量full和empty来执行存储项目的缓冲区的计数。还有一个互斥锁来控制对关键部分的访问。我有两个函数:一个基于一个简单的计算创建一个项目:threads * 1000000 + count,而另一个消耗它。
缓冲区中有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]);
}
}