【发布时间】:2015-01-15 15:39:21
【问题描述】:
我有一个简单的程序来模拟 C 中的读者-作者问题。要求用户输入作者数和读者数。然后创建随机数量的写入器 - 线程和读取器 - 线程。项目的写入由全局变量 itemsCount 模拟 - 它表示新插入项目的 ID (itemsCount + 1)。我认为到目前为止,该程序运行良好。
但现在我必须展示由错误的写入同步引起的写入冲突。我认为这足以简单地删除声明 sem_wait(&w); 或严重初始化信号量 - 例如 sem_init(&w,0,5);
但它什么也没做,我看不到任何写作冲突。我想,在输出中我会看到如下内容:
Writer 1 写入项目 --> 项目数:1 |项目名称:作家1
Writer 2 写入项目 --> 项目数:1 |物品名称:作家2
(冲突:一个数字的两个项目)。但是这一切都没有发生。
我哪里错了?
具有良好同步性的代码:
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#define MAX_READERS 10
#define MAX_WRITERS 10
sem_t w; // semaphor for write access
sem_t m; // mutex
int rc=0; // readers count
int writersCount; // how many writers does user want
int readersCount; // how many readers does user want
pthread_t writersThread[MAX_WRITERS*5], readersThread[MAX_READERS*5]; // threads for writers and readers
int writeCount[MAX_WRITERS], readCount[MAX_READERS]; // how many times did each writer write and each reader read
int itemsCount=0; // how many items is stored in the "DB"
void *writer(void *i)
{
int a = *((int *) i);
sem_wait(&w); // P(w)
printf("Writer %d writes item --> number of item: %d | name of item: Writer %d\n", a+1, ++itemsCount, a+1);
writeCount[a]++;
sem_post(&w); // V(w)
return 0;
}
void *reader(void *i)
{
int a = *((int *) i);
sem_wait(&m); // P(m)
rc++;
if (rc == 1) {
sem_wait(&w); // P(w)
}
sem_post(&m); // V (m)
printf("Reader %d reads from DB.\n", a+1);
readCount[a]++;
sem_wait(&m); // P(m)
rc--;
if (rc == 0) {
sem_post(&w); // V(w)
}
sem_post(&m); // V(m)
return 0;
}
int randomCount() // returns random integer between 1 and 5
{
return 1 + 5.0 * rand() / RAND_MAX;
}
int main()
{
srand(time(NULL));
sem_init(&w,0,1); // semaphore initialization
sem_init(&m,0,1);
int i;
printf("Enter count of writers (max. %d):", MAX_WRITERS);
scanf("%d",&writersCount);
if (writersCount > MAX_WRITERS) {
fprintf(stderr, "Max count of wirters is: %d\n", MAX_WRITERS);
return 1;
}
printf("Enter count of readers (max. %d):", MAX_READERS);
scanf("%d",&readersCount);
if (writersCount > MAX_READERS) {
fprintf(stderr, "Max count of readers is %d\n", MAX_READERS);
return 1;
}
printf("---------------------------------------------\n");
int readerIndexes[readersCount]; // reader indexes (will be passed to thread)
int writerIndexes[readersCount]; // writer indexes (will be passed to thread)
int totalReaders = 0;
int totalWriters = 0;
for (i=0; i<readersCount; i++) // create readers (how many did user enter)
{
int j;
int count;
readerIndexes[i] = i;
count = randomCount();
for (j=0; j<count; j++) // let the reader read randomly from 1 to 5 times
{
pthread_create(&readersThread[totalReaders++], NULL, reader, &readerIndexes[i]);
}
}
for (i = 0 ; i < writersCount ; i++) // create writers (how many did user enter)
{
int j;
int count;
writerIndexes[i] = i;
count = randomCount();
for (j=0;j<count;j++) // let the writer write randomly from 1 to 5 times
{
pthread_create(&writersThread[totalWriters++], NULL, writer, &writerIndexes[i]);
}
}
for (i=0;i<totalWriters;i++) // join the threads
{
pthread_join(writersThread[i], NULL);
}
for (i=0;i<totalReaders;i++)
{
pthread_join(readersThread[i], NULL);
}
printf("---------------------------------------------\n");
for (i=0;i<readersCount;i++)
{
printf("Reader %d read %d times\n", i+1, readCount[i]);
}
for (i=0;i<writersCount;i++)
{
printf("Writer %d wrote %d times\n", i+1, writeCount[i]);
}
sem_destroy(&w);
sem_destroy(&m);
return 0;
}
输出:
Enter count of writers (max. 10):5
Enter count of readers (max. 10):5
---------------------------------------------
Reader 1 reads from DB.
Reader 1 reads from DB.
Reader 2 reads from DB.
Reader 2 reads from DB.
Reader 2 reads from DB.
Reader 2 reads from DB.
Reader 3 reads from DB.
Reader 3 reads from DB.
Reader 4 reads from DB.
Reader 4 reads from DB.
Reader 4 reads from DB.
Writer 1 writes item --> number of item: 1 | name of item: Writer 1
Writer 1 writes item --> number of item: 2 | name of item: Writer 1
Writer 1 writes item --> number of item: 3 | name of item: Writer 1
Writer 2 writes item --> number of item: 4 | name of item: Writer 2
Writer 2 writes item --> number of item: 5 | name of item: Writer 2
Writer 2 writes item --> number of item: 6 | name of item: Writer 2
Writer 3 writes item --> number of item: 7 | name of item: Writer 3
Writer 3 writes item --> number of item: 8 | name of item: Writer 3
Writer 3 writes item --> number of item: 9 | name of item: Writer 3
Writer 3 writes item --> number of item: 10 | name of item: Writer 3
Writer 4 writes item --> number of item: 11 | name of item: Writer 4
Writer 5 writes item --> number of item: 12 | name of item: Writer 5
Writer 5 writes item --> number of item: 13 | name of item: Writer 5
Writer 5 writes item --> number of item: 14 | name of item: Writer 5
Reader 4 reads from DB.
Reader 4 reads from DB.
Reader 5 reads from DB.
Reader 5 reads from DB.
Reader 5 reads from DB.
Reader 5 reads from DB.
---------------------------------------------
Reader 1 read 2 times
Reader 2 read 4 times
Reader 3 read 2 times
Reader 4 read 5 times
Reader 5 read 4 times
Writer 1 wrote 3 times
Writer 2 wrote 3 times
Writer 3 wrote 4 times
Writer 4 wrote 1 times
Writer 5 wrote 3 times
非常感谢
【问题讨论】:
-
也许我有解决方案。需要给writer写类似的代码:usleep(rand() % 10); - 假装一些动作。但我不确定为什么?是不是因为不然线程会跑得太快?
-
另一件事是将全局变量加载到线程的局部变量中,增加局部变量,然后将其再次传递给全局变量。这个作家的代码完美地工作:
-
void *writer(void *i) { int a = *((int *) i); int myItemsCount; sem_wait(&w); // P(w) myItemsCount = itemsCount; myItemsCount++; usleep(rand() % 10); itemsCount = myItemsCount; printf("Writer %d writes item --> number of item: %d | name of item: Writer %d\n", a+1, myItemsCount, a+1); writeCount[a]++; sem_post(&w); // V(w) return 0; }
标签: c