【发布时间】:2015-05-08 10:04:19
【问题描述】:
我用 C 编写了简单的消费者-生产者程序。当我有 1 个生产者和 1 个消费者时,它运行良好。但是当我增加消费者数量时,它的行为很奇怪。
- 我启动生产者进程
- 制片人正在制作
- 我启动消费者进程
- 消费者在消费,生产者在生产
- 我启动 2 号消费者进程
- 消费者进程 no2 永远不会获得元素
- 当我启动消费者 no3、no4... 等等时,也会发生同样的情况
第二个问题:
- 生产者生产了最多的元素
- 消费者消费所有元素,但生产者不再继续生产
我不知道为什么会这样。
代码:
制作人:
#include <semaphore.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <fcntl.h>
#include "common.h"
int memoryID;
struct wrapper *memory;
int rc;
void atexit_function() {
rc = shmctl(memoryID, IPC_RMID, NULL);
rc = shmdt(memory);
sem_destroy(&memory->pmutex);
sem_destroy(&memory->cmutex);
sem_destroy(&memory->empty);
sem_destroy(&memory->full);
}
int main(int argc, char **argv) {
atexit(atexit_function);
//creating key for shared memory
srand(time(NULL));
key_t sharedMemoryKey = ftok(".", MEMORY_KEY);
if (sharedMemoryKey == -1) {
perror("ftok():");
exit(1);
}
memoryID = shmget(sharedMemoryKey, sizeof(struct wrapper), IPC_CREAT | 0600);
if (memoryID == -1) {
perror("shmget():");
exit(1);
}
memory = shmat(memoryID, NULL, 0);
if (memory == (void *) -1) {
perror("shmat():");
exit(1);
}
//initialization
printf("Initializtaion !\n");
memset(&memory->array, 0, sizeof(memory->array));
sem_init(&memory->pmutex, 0, 1);
sem_init(&memory->cmutex, 0, 1);
sem_init(&memory->empty, 0, SIZE_OF_ARRAY);
sem_init(&memory->full, 0, 0);
memory->n = -1;
if (memoryID == -1) {
perror("shmget(): ");
exit(1);
}
while(1)
{
int r = rand();
sem_wait(&memory->empty);
sem_wait(&memory->pmutex);
memory->n++;
(memory->array)[memory->n]=r;
printf("Adding task\t Value:%d\tNumber of tasks waiting:%d \n",r,memory->n);
usleep(10000);
sem_post(&memory->pmutex);
sem_post(&memory->full);
}
}
消费者:
#include <semaphore.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "common.h"
#include <sys/shm.h>
int memoryID;
struct wrapper *memory;
int check_prime(int a);
int main(int argc, char **argv) {
srand(time(NULL));
key_t sharedMemoryKey = ftok(".",MEMORY_KEY);
if(sharedMemoryKey==-1)
{
perror("ftok():");
exit(1);
}
memoryID=shmget(sharedMemoryKey,sizeof(struct wrapper),0);
if(memoryID==-1)
{
perror("shmget(): ");
exit(1);
}
memory = shmat(memoryID,NULL,0);
if(memory== (void*)-1)
{
perror("shmat():");
exit(1);
}
while(1)
{
sem_wait(&memory->full);
sem_wait(&memory->cmutex);
int n = memory->n;
int temp = (memory->array)[n];
printf("Removed item: %d\tPrime:%d\tNumer of tasks left:%d\n",
temp, check_prime(temp),n);
memory->n--;
usleep(10000);
sem_post(&memory->cmutex);
sem_post(&memory->empty);
}
}
common.h:
#define MEMORY_KEY 12
#define SIZE_OF_ARRAY 10
struct wrapper
{
int array[SIZE_OF_ARRAY];
sem_t empty;
sem_t pmutex;
sem_t cmutex;
sem_t full;
int n;
};
【问题讨论】:
-
我认为您必须为其他流程留出时间来获取 sem。例如。 sem 发布后睡一会儿。
-
不幸的是它没有帮助
-
发布的代码似乎过于复杂。似乎没有/零需要任何信号量。数据需要互斥体、计数器和数组。当没有可处理的对象/int 时,消费者需要睡一会儿。当数组已满时,生产者需要休眠一会儿。我还建议,为避免未及时处理旧数据,将数组视为带有头尾指针的循环列表
标签: c concurrency posix ipc