【发布时间】:2019-05-07 14:03:02
【问题描述】:
我想用 C/C++ 编写简单的多线程应用程序。函数 funProducent 产生 100 个值,如果随机生成的值在给定范围内,则将 char 添加到缓冲区。函数 funKonzument 从缓冲区获取值。这是我的代码:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#define BUFFER_LIMIT 20
struct struktura{
pthread_mutex_t mutex;
pthread_cond_t bufferNotFull;
pthread_cond_t bufferNotEmpty;
int bufferIndex;
char * buffer;
int junk;
};
void * funProducent(void *arg){
struktura * data = (struktura *) arg;
int i = 0;
while (i < 100) {
pthread_mutex_lock(&data->mutex);
if(data->bufferIndex == BUFFER_LIMIT - 1){
pthread_cond_wait(&data->bufferNotFull, &data->mutex);
}
int randomValue = (rand() % 20) + 1;
if( randomValue < 13 ){
data->buffer[++data->bufferIndex] = 'a';
printf("%2d : Producent at index %d added %c\n", i, data->bufferIndex, data->buffer[data->bufferIndex]);
pthread_cond_signal(&data->bufferNotEmpty);
} else {
data->junk++;
}
pthread_mutex_unlock(&data->mutex);
i++;
}
printf("producent is done\n");
}
void * funKonzument(void *arg){
struktura * data = (struktura *) arg;
int i = 0;
while (i + data->junk < 100) {
printf("%d\n", i + data->junk);
pthread_mutex_lock(&data->mutex);
if(data->bufferIndex < 0){
pthread_cond_wait(&data->bufferNotEmpty, &data->mutex);
}
printf("%2d : Konzument at index %d consumed %c\n", i, data->bufferIndex, data->buffer[data->bufferIndex]);
data->bufferIndex--;
pthread_cond_signal(&data->bufferNotFull);
pthread_mutex_unlock(&data->mutex);
i++;
}
printf("konzument is done\n");
}
int main(int argc, char** argv) {
pthread_t threadProducent, threadKonzument;
struktura threadData;
threadData.buffer = (char *) malloc(sizeof(char) * BUFFER_LIMIT);
threadData.bufferIndex = -1;
threadData.bufferNotFull = PTHREAD_COND_INITIALIZER;
threadData.bufferNotEmpty = PTHREAD_COND_INITIALIZER;
threadData.mutex = PTHREAD_MUTEX_INITIALIZER;
threadData.junk = 0;
pthread_create(&threadProducent, NULL, funProducent, &threadData);
pthread_create(&threadKonzument, NULL, funKonzument, &threadData);
pthread_join(threadProducent, NULL);
pthread_join(threadKonzument, NULL);
free(threadData.buffer);
pthread_mutex_destroy(&threadData.mutex);
pthread_cond_destroy(&threadData.bufferNotFull);
pthread_cond_destroy(&threadData.bufferNotEmpty);
return 0;
}
当我尝试运行此代码时,有时它会卡在 funKonzument 中:
pthread_cond_wait(&data->bufferNotEmpty, &data->mutex);
但是...当我在 funProducent 方法中更改条件时:
if( randomValue < 13 )
到
if( randomValue > 8 )
一切正常。谁能解释一下这两个条件之间有什么神奇的区别?
【问题讨论】:
-
你从 100 中检索一个随机数,并检查它是否低于 13,它有大约 10% 的机会,而当你检查它是否高于 8 时,你已经有 90% 的几率是正确的。我会说你的线程没有正确运行,或者它可能只是很慢。您应该尝试附加调试器并逐步执行代码并查看发生了什么。您可能遇到了一些死锁,这种情况很少发生,但在不添加值时更明显
-
也可以考虑放弃
pthread,改用std::thread和std::mutex。 -
你确定你问的是C++而不是C吗?除了一些省略的
struct说明符之外,您根本没有使用 C++ 特定功能或标准库。 -
变量 randomValue 应该是 1 到 20 之间的值,所以值大于 8 的概率应该与值小于 13 的概率相同,不是吗?
-
这有点暗示
rand()不是很随机(一个已知问题)。这也是真正的C代码。您所做的几乎所有事情都有更好的 C++ 替代方案。std::vector、std::thread、std::mutex、std::conditional_variable、std::random
标签: c++ c pthreads conditional-statements mutex