我正在研究一个简单的生产者 - 消费者问题,在C中使用OpenMP。
我的程序创建了4个线程,其中两个是消费者,两个是生产者。每个制作人将一个角色放在缓冲区中,消费者只需打印该角色。
我的目标是同步生产者/消费者,以便每个生产者将生成字母表中的下一个按顺序字符,并且每个消费者将打印放置在缓冲区中的下一个按顺序字符。
这是我的代码:
#include <stdio.h>
#include <unistd.h>
#include <omp.h>
#define SIZE 5
#define NUMITER 26
char buffer[SIZE];
int nextin = 0;
int nextout = 0;
int count = 0;
int empty = 1;
int full = 0;
int i,j;
void put(char item)
{
buffer[nextin] = item;
nextin = (nextin + 1) % SIZE;
count++;
if (count == SIZE)
full = 1;
if (count == 1) // buffer was empty
empty = 0;
}
void producer(int tid)
{
char item;
while( i < NUMITER)
{
#pragma omp critical
{
item = 'A' + (i % 26);
put(item);
i++;
printf("%d Producing %c ...\n",tid, item);
}
sleep(1);
}
}
char get()
{
char item;
item = buffer[nextout];
nextout = (nextout + 1) % SIZE;
count--;
if (count == 0) // buffer is empty
empty = 1;
if (count == (SIZE-1))
// buffer was full
full = 0;
return item;
}
void consumer(int tid)
{
char item;
while(j < NUMITER )
{
#pragma omp critical
{
j++;
item = get();
printf("%d ...Consuming %c\n",tid, item);
}
sleep(1);
}
}
int main()
{
int tid;
i=j=0;
#pragma omp parallel firstprivate(i,j) private(tid) num_threads(4)
{
tid=omp_get_thread_num();
if(tid%2==1)
{
producer(tid);
}
else
{
consumer(tid);
}
}
}
这是输出:
0 Producing A ...
2 Producing B ...
1 ...Consuming A
3 ...Consuming B
1 ...Consuming <---- notice empty
0 Producing C ...
3 ...Consuming <---- notice empty
2 Producing D ...
2 Producing E ...
3 ...Consuming E
0 Producing F ...
1 ...Consuming F
2 Producing G ...
3 ...Consuming G
0 Producing H ...
1 ...Consuming H
3 ...Consuming D
2 Producing I ...
0 Producing J ...
1 ...Consuming J
3 ...Consuming F
2 Producing K ...
0 Producing L ...
1 ...Consuming L
3 ...Consuming H
2 Producing M ...
0 Producing N ...
1 ...Consuming N
3 ...Consuming J
2 Producing O ...
0 Producing P ...
1 ...Consuming P
3 ...Consuming L
2 Producing Q ...
0 Producing R ...
1 ...Consuming R
2 Producing S ...
3 ...Consuming S
0 Producing T ...
1 ...Consuming T
3 ...Consuming P
2 Producing U ...
0 Producing V ...
1 ...Consuming V
2 Producing W ...
3 ...Consuming W
0 Producing X ...
1 ...Consuming X
2 Producing Y ...
3 ...Consuming Y
0 Producing Z ...
1 ...Consuming Z
那些没有打印字符的空行表示我没有实现我应该达到的同步。 我错过了什么?
提前感谢您的任何帮助或想法。
答案 0 :(得分:1)
所以@Jlghtuse是正确的,有数据竞争,这是因为关键区域的错误声明。
你看我宣布我的关键领域:
void consumer(int tid)
{
char item;
while(j < NUMITER )
{
#pragma omp critical
{
j++;
item = get();
printf("%d ...Consuming %c\n",tid, item);
}
sleep(1);
}
}
和
void producer(int tid)
{
char item;
while( i < NUMITER)
{
#pragma omp critical
{
item = 'A' + (i % 26);
put(item);
i++;
printf("%d Producing %c ...\n",tid, item);
}
sleep(1);
}
}
这导致消费者无法访问其他消费者关键区域,但产生了,反之亦然。解决方案相当简单,我只需要为关键区域添加一个通用名称,现在消费者的关键区域对于生产者来说也是至关重要的,反之亦然。
这是用于声明关键区域的正确代码:
#pragma omp critical (CRIT)