问题
I am working on a simple producer-consumer problem, using OpenMP in C.
My program creates 4 threads, two of which are consumers and two producers. Each producer places a character in a buffer, and the consumers just print the character.
My aim is to synchronize the producers/consumers so that each producer will produce the next in order character of the alphabet and each consumer will print the next in order character that is placed in the buffer.
This is my code:
#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);
}
}
}
And this is the output :
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
Those empty lines that have not printed a character indicate that I dont achieve the synchronization that I should. What am I missing?
Thank you in advance for any help or ideas.
回答1:
So @Jlghtuse was correct, there were data races and that was because of mistaken declarations of the critical areas.
You see I declared my critical areas:
void consumer(int tid)
{
char item;
while(j < NUMITER )
{
#pragma omp critical
{
j++;
item = get();
printf("%d ...Consuming %c\n",tid, item);
}
sleep(1);
}
}
and
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);
}
}
That resulted in consumers not having access into other consumers critical area but produces had and vice versa. The solution was rather simple, I just had to add a common name for the critical areas and now a critical area for a consumer is critical for a producer too, and vice versa.
This is the correct code for declaring the critical areas:
#pragma omp critical (CRIT)
来源:https://stackoverflow.com/questions/20041030/openmp-producer-consumer-unexpected-result