读者---写者问题

                                           经典进程同步与互斥问题
读者---写者问题
1.问题描述
一个数据对象若被多个并发进程所共享,且其中一些进程只要求读该数据对象的内容,而另一些
进程则要求写操作,对此,把只想读的进程称为“读者”,而把要求写的进程称为“写者”。在
读者--写着问题中,任何时刻要求“写者”最多只允许有一个,而读者则允许有多个。因为多个
读者的行为互不干扰,他们只是读数据,而不改变数据对象的内容,而写者则不同,他们要改变数据对象的内容,如果他们同时操作,则数据对象的内容将会改变的不可知。所以对共享资源的读写操作的限制条件是:
1>允许任意多的读进程同时读;
2>一次只允许一个写进程写操作;
3>如果有一个写进程正在进行写操作,禁止任何读进程进行读操作。
2.用信号量解决读者--写着问题
为了解决“写着与写着”和“写着与第一个读者”的互斥问题即可,为此引入互斥信号量Wmutex。
为了记录谁是第一个读者,可以用一个全局整型变量Rcount做一个计数器。而在解决问题的过程中,由于使用了全局变量Rcount,该变量又是一个临界资源,对于他的访问仍需互斥进行,所以需要
一个互斥信号量Rmutex。
3.思考问题
对于读者---写者问题,有以下三种策略。
1>读者优先。即当读者进行读时,后续的写者必须等待,直到所有的读者均离开后,写着才可进入。
2>写者优先。即当一个写者到来时,只有那些已经获得授权允许读的进程才允许完成他们的操作,
写者之后到来的读者将被推迟,直到写者完成。在该策略中,如果有一个不可中断的连续的写者,
读者进程会被无限期的推迟。
3>公平策略。以上两种策略,读者或写进程中一个对一个有绝对的优先权,Hoare提出了一种更公平
的策略,由如下规则定义。
规则1:在一个读序列中,如果有写者在等待,那么就不允许有新的读者开始执行。
规则2:在一个写操作结束时,所有等待的读者应该比下一个写者有更高的优先权。
对于公平策略,又如何解决呢?

#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
int Rcount=0,num=0;   //被保护的全局变量
sem_t Wmutex,Rmutex,mutex;
void* read1(void *arg)
{
 sem_wait(&mutex);
 sem_wait(&Rmutex);//读者到来
 if(Rcount==0)
 {
   printf("第一个读者到来\n");
   sem_wait(&Wmutex);
 }
 Rcount=Rcount+1;//读者数目
 sem_post(&Rmutex);
 sem_post(&mutex);
 printf("线程%lu正在进行读数据%d\n",pthread_self(),num);
 sleep(1);
 sem_wait(&Rmutex);//读者阅读结束
 Rcount=Rcount-1;
 if(Rcount==0)//所有的读者阅读结束
 {
     sem_post(&Wmutex);
     printf("读者全部退出\n");
 }
 sem_post(&Rmutex);
}

void* write1(void *arg)
{
 sem_wait(&mutex);
 sem_wait(&Wmutex);
 num=num+1;
 printf("线程%lu正在进行写数据%d\n",pthread_self(),num);
 sem_post(&Wmutex);
 sem_post(&mutex);
}
int main(int argc,char *argv[])
{     int i=0;
      int j=3;
      pthread_t tid[5];
      sem_init(&Wmutex,0,1);
      sem_init(&Rmutex,0,1);
      sem_init(&mutex,0,1);
      while(i<=2)
        {
           if((pthread_create(&tid[i],NULL,read1,NULL))!=0)
                {
                        printf("can‘t create pthread.\n");
                       exit(0);
                }
                i++;
        }
        while(j<=4)
        {
           if((pthread_create(&tid[j],NULL,write1,NULL))!=0)
                {
                        printf("can‘t create pthread.\n");
                       exit(0);
                }
                j++;
        }
      for(i=0;i<5;i++)
        pthread_join(tid[i],NULL);
      sem_destroy(&Wmutex);
      sem_destroy(&Rmutex);
      printf("程序运行结束\n");
      return 0;
}

写者优先

#include <pthread.h>
#include <semaphore.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include<stdlib.h>
int Rcount=0,num=0;   //被保护的全局变量
sem_t Wmutex,Rmutex;
void* read1(void *arg)
{
 sem_wait(&Rmutex);//读者到来
 if(Rcount==0)
 {
   printf("第一个读者到来\n");
   sem_wait(&Wmutex);
 }
 Rcount=Rcount+1;//读者数目
 sem_post(&Rmutex);
 printf("线程%lu正在进行读数据%d\n",pthread_self(),num);
 sleep(1);
 sem_wait(&Rmutex);//读者阅读结束
 Rcount=Rcount-1;
 if(Rcount==0)//所有的读者阅读结束
 {
     sem_post(&Wmutex);
     printf("读者全部退出\n");
 }
 sem_post(&Rmutex);

}

void* write1(void *arg)
{
 sem_wait(&Wmutex);
 num=num+1;
 printf("线程%lu正在进行写数据%d\n",pthread_self(),num);
 sem_post(&Wmutex);
}
int main(int argc,char *argv[])
{     int i=0;
      int j=3;
      pthread_t tid[5];
      sem_init(&Wmutex,0,1);  // 空闲的
      sem_init(&Rmutex,0,1);  // 忙的
      while(i<=2)
        {
           if((pthread_create(&tid[i],NULL,read1,NULL))!=0)
                {
                        printf("can‘t create pthread.\n");
                       exit(0);
                }
                i++;
        }
        while(j<=4)
        {
           if((pthread_create(&tid[j],NULL,write1,NULL))!=0)
                {
                        printf("can‘t create pthread.\n");
                       exit(0);
                }
                j++;
        }
      for(i=0;i<5;i++)
        pthread_join(tid[i],NULL);
      sem_destroy(&Wmutex);
      sem_destroy(&Rmutex);
      printf("程序运行结束\n");
      return 0;
}

读者优先

时间: 2024-10-16 05:23:26

读者---写者问题的相关文章

利用JAVA线程安全队列简单实现读者写者问题。

常见的操作系统教科书中,会使用互斥锁来实现读者线程和写者线程的同步问题,但是在JDK5推出线程安全队列之后,将该问题变得异常简单. java.util.concurrent.ConcurrentLinkedQueue 是线程安全的非阻塞队列,其实很容易想到,非阻塞队列当线程需要等待的时候,则不会阻塞等待,而是直接根据情况返回. java.util.concurrent.LinkedBlockingQueue 是线程安全的阻塞队列,该队列能够在很多情况下对线程进行阻塞,比如队列为空时调用take(

Linux多线程实践(6) --Posix读写锁解决读者写者问题

Posix读写锁 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); int pthread_rwlock_destroy(pthread_rwlock_t *rwlock); int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); int pthread_rwlock_wrlock(pthre

秒杀多线程第十一篇 读者写者问题

与上一篇<秒杀多线程第十篇 生产者消费者问题>的生产者消费者问题一样,读者写者也是一个非常著名的同步问题.读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者在读文件时写者也不去能写文件. 上面是读者写者问题示意图,类似于生产者消费者问题的分析过程,首先来找找哪些是属于“等待”情况. 第一.写者要等到没有读者时才能去写文件. 第二.所有读者要等待写者完成写文件后才能去读文件. 找完“等待”情况后,再看看有没有要互斥访问的资源.由

用信号量和读写锁解决读者写者问题

读者写者问题是非常经典的同步问题,本文首先用信号量来解决这个问题,并结合代码分析什么是读者优先.什么是写者优先,然后给出读写锁的解决方案,并指出在Linux下读写锁的注意事项. 读者写者问题 读者写者问题描述的是这么一种情况:对象在多个线程(或者进程)之间共享,其中一些线程只会读数据,另外一些线程只会写数据.为了保证写入和读取的正确性,我们需要保证,只要有线程在写,那么其他线程不能读,否则可能读到写了一半的数据:另外,也不能有两个线程同时写,否则导致数据错乱.当然,多个线程是可以同时读数据. 读

多线程---读者写者问题

有几种思路 1.利用信号量来实现读者写者的互斥(读者和读者之间是并行的) public class ReaderAndWriter { private static AtomicInteger reader = new AtomicInteger(); private static AtomicInteger blocked = new AtomicInteger(); //用来对读者写者互斥 private static Semaphore ws = new Semaphore(1,true)

读者写者模式

在编写多线程的时候,有一种情况是比较常见的.那就是,有些公共数据修改的机会比较少.相较改写,它们读的机会反而多的多. 读者写者模式:三种关系,两类人,一个场所 三种关系: 读者与读者:无关系 写者与写者:互斥 读者与写者:同步与互斥 两类人:读者,写者 一个场所:同一临界资源(数据) 自旋锁:如果所等待条件不满足,不挂起,一直申请锁.适宜某个线程占用锁时间较短. 当不断有多个读者准备读时,如果有写者到来,此时应该当前读者读完后,提高写者优先级,下个进入临界区的是写者.---------写者优先,

多线程面试题系列(14):读者写者问题继 读写锁SRWLock

在第十一篇文章中我们使用事件和一个记录读者个数的变量来解决读者写者问题.问题虽然得到了解决,但代码有点复杂.本篇将介绍一种新方法--读写锁SRWLock来解决这一问题.读写锁在对资源进行保护的同时,还能区分想要读取资源值的线程(读取者线程)和想要更新资源的线程(写入者线程).对于读取者线程,读写锁会允许他们并发的执行.当有写入者线程在占有资源时,读写锁会让其它写入者线程和读取者线程等待.因此用读写锁来解决读者写者问题会使代码非常清晰和简洁. 下面就来看看如何使用读写锁,要注意编译读写锁程序需要V

Java实现生产者消费者问题与读者写者问题

摘要: Java实现生产者消费者问题与读者写者问题 1.生产者消费者问题 生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品.解决生产者/消费者问题的方法可分为两类:(1)采用某种机制保护生产者和消费者之间的同步:(2)在生产者和消费者之间建立一个管道.第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式.第二种管道缓冲区不易控制,被传输数据对象不易于封装等,实用性不强. 同步问题核心在

秒杀多线程第十一篇 读者写者问题(续)

java实现: 本问题的关键是读者写者之间的同步问题,尤其使用java来操作. 1.等待读者,使用CountDownLatch mReaderLatch, 但是CountDownLatch只能使用一次,所以需要每次都new 一个. 或者可以考虑使用semaphore代替,但是semaphore需要acquire(READ_THREAD_SIZE)才能等待所有读者线程结束. 2.等待写入操作.使用semaphore来控制, mWriteSema.release(READ_THREAD_SIZE);

转---秒杀多线程第十一篇 读者写者问题

与上一篇<秒杀多线程第十篇 生产者消费者问题>的生产者消费者问题一样,读者写者也是一个非常著名的同步问题.读者写者问题描述非常简单,有一个写者很多读者,多个读者可以同时读文件,但写者在写文件时不允许有读者在读文件,同样有读者在读文件时写者也不去能写文件. 上面是读者写者问题示意图,类似于生产者消费者问题的分析过程,首先来找找哪些是属于“等待”情况. 第一.写者要等到没有读者时才能去写文件. 第二.所有读者要等待写者完成写文件后才能去读文件. 找完“等待”情况后,再看看有没有要互斥访问的资源.由