读者-写者问题为数据库访问建立了一个模型。
设想一个飞机订票系统,其中许多竞争的进程试图写其中的数据。多个进程同时读数据库是可以接受的,但如果一个进程正在更新(写)数据库,则所有其他进程都不能访问该数据库,即使读操作也不行。这里的问题是如何对读者和写者进行编程。
在该解法中,第一个读者对信号量db执行down操作。随后的读者只是递增一个计数器rc。当读者离开时,就递减这个计数器。最后一个读者离开时对信号量db执行up操作,这样就允许一个阻塞的写者访问该数据库。
有个问题:如果每2秒钟有一个读者进来,每个读者读5秒钟,这样写者就永远没有机会了。
可以稍微改变下程序写法:在一个读者到达,且一个写者在等待时,读者在写者之后被挂起,而不是允许立即进入。这种方案的缺点是并发度和效率比较低。
#include <pthread.h>
#include <stdio.h>
#define READING_TIME 4
#define WRITTING_TIME 2
#define TIME_INTERVAL_READER 1
#define TIME_INTERVAL_WRITER 5
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER,db=PTHREAD_MUTEX_INITIALIZER;
int rc=0;
int count=0;
void read_data_base(int i)
{
printf("第 %d 个读者在读\n", i);
sleep(READING_TIME);
printf("第 %d 个读者读完\n", i);
}
void write_data_base()
{
printf("正在写数据...\n");
sleep(WRITTING_TIME);
}
void* reader(void* arg)
{
while(1)
{
pthread_mutex_lock(&mutex); //获得对rc的访问权
rc=rc+1;
count=count+1;
if(rc==1) pthread_mutex_lock(&db); //第一个读者时,不让写者访问
pthread_mutex_unlock(&mutex); //释放对rc的访问权
read_data_base(count); //读数据
pthread_mutex_lock(&mutex); //获取对rc的访问权
rc=rc-1;
if(rc==0) pthread_mutex_unlock(&db);//最后一个读者,释放db访问权
pthread_mutex_unlock(&mutex);
sleep(TIME_INTERVAL_READER);
}
}
void* writer(void* arg)
{
while(1)
{
sleep(TIME_INTERVAL_WRITER);
pthread_mutex_lock(&db); //获得db访问
write_data_base(); //更新数据
pthread_mutex_unlock(&db); //释放访问权
}
}
int main()
{
pthread_t tid1,tid2;
pthread_create(&tid1, NULL, reader,NULL);
pthread_create(&tid2, NULL, writer,NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
return 0;
}
上面的效率较低,在读的过程中一直占用着资源。