我编写了一个模拟生产者消费者问题的程序,我遇到了几个问题。这是使用 Win32 API 编写的。
我正在使用两个满和空的信号量来对存储项目的缓冲区执行计数。还有一个互斥锁来控制对临界区的访问。我有两个功能:一个基于简单的计算创建一个项目:线程 * 1000000 + 计数,而另一个消耗它。
缓冲区中有 10 个空格,但是程序应该希望能够为不同数量的空格和线程工作。生产者线程通过缓冲区然后重新开始,直到信号量达到 10。我遇到了两个问题,我似乎也找不到解决方案,也没有在调试器中获得很多细节。
1)具有 printf() 函数的注释部分每次都会使线程崩溃。没有任何东西被打印到控制台。我也尝试过只使用一个字符串,而没有输出其他变量。没有成功。我发现 printf() 在多线程环境中使用时可能会遇到问题的文档,但是在这种情况下,它位于关键部分内,并且在第一次尝试时会崩溃。如何将该信息打印到控制台?
2)当我删除打印语句并运行代码时,线程每次仍然在不同的点崩溃。我不知道为什么。生产者线程应该等待空信号量和互斥体,将项目放入,然后增加完整信号量的计数(表示已添加项目)。当它达到 10 时,它应该停止。消费者线程等待完整的信号量和互斥量,删除一个项目,然后增加空信号量的计数。我写的方式有什么导致这些线程退出的吗?
这就是我得到的:
程序“[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]);
}
}