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

1. 最多的问题

做实验的时候,大部分同学多半已经忘了之前学的内容了,这种情况下,合理的做法是:先复习下理论内容(在信号量同步实验,已经点出这点了)。

看了交上来的报告,很多同学不懂原理,也不复习,直接就去找别人的实现,于是就有了定义5个信号量,给写者计数的迷操作。

代码只是你思路的一种呈现,先搞懂原理,甚至可以先写下伪代码(先软件设计),再去写代码(再软件实现)。

2. 如果你复习了

如果你按这个思路来,应该会轻松许多。

你应该很容易找到PPT以个这两页的内容。

需要哪些信号量:

reader-writer-vars

读者和写者的伪代码:

reader-writer-pseudo-codes

2.1 问题

读者-写者问题是经典IPC问题,解决一个文件被多个进程共享问题。

  • 允许多个读者读同一个文件

  • 但不允许读者和写者同时访问

  • 也不允许多个写者同时访问

2.2 思路

咱们说过,先想想需要哪些信号量,换句话说,有哪些什么东西(找到互斥资源)需要保护。

本实验,读者和写者互斥访问的资源是文件,因此文件是咱们的临界资源。

咱们一步步来:

(1)不允许多个写者同时访问

文件需要一把互斥锁(mutex),

semaphore mutex=1;                 // 保护文件

写者的函数伪代码,很容易写出来(反次,一次只能一个写者访问),

// 写者
writer(){
    P(mutex)

    write

    V(mutex)
}

(2)不允许读者和写者同时访问

先不考虑多个读者之间,只考虑读者和写者,那么,

  • 有写者写的时候,读者不能读
  • 有读者读的时候,写者不能写

于是,有了读者初步伪代码,

// 读者
reader(){
    P(mutex)

    read

    V(mutex)
}

(3)允许多个读者读同一个文件

在(2)的基础上,再加上允许多个读者同时读一个文件(因为读不会改变内容)。想象下,现在有一个读者想读这个文件,

  • 如果该文件有写者在写,已经上了锁,读不了,阻塞
  • 如果该文件没有人在读,上锁,就可以读了
  • 如果该文件已经有人在读,说明已经有其他读者给文件上锁了,我直接读就行了

分析到这里,你会发现,需要一个变量来统计读者的数目,

int reader_count = 0;            // 读者计数

可以初步写出下列伪代码,第一个读reader_count==0,给文件上锁;读完,最后一个离开reader_count==0,给文件解锁。

// 读者
reader(){
    if(reader_count==0){
        P(mutex);
    }
    reader_count++;

    read

    reader_count--;
    if(reader_count==0){
        V(mutex);
    }
}

但上述操作有个问题,reader_count是多个读者的共享变量,对reader_count操作包含,多个步骤,比如:

if(reader_count==0){
    P(mutex);
}
reader_count++;

存在互斥访问的可能,因此需要保护起来,咱们再定义一个互斥量,用来保护reader_count这个变量,

semaphore mutex_reader_count=1; // 保护reader_count变量

reader_count操作,属于临界区,现在将其保护起来,于是咱们就有了如下完整的伪代码:

// 读者
reader(){
    P(mutex_reader_count);        // 保护reader_count
    if(reader_count==0){
        P(mutex);
    }
    reader_count++;
    V(mutex_reader_count);        // 对reader_count操作完成了

    read

    P(mutex_reader_count);        // 保护reader_count
    reader_count--;
    if(reader_count==0){
        V(mutex);
    }
    V(mutex_reader_count)        // 对reader_count操作完成了
}

3.3 实现

有了上述的思路,接下来就是实现。置换上述伪代码:

  • 信号量创建,sem_init
  • PV操作分别对应于sem_waitsem_post
  • readwrite部分,读取文件和写入文件

4. 写在最后

知识是相通的,不管将来你做什么,希望你能从这些实验获取到一些经验。

  • 初一看很难,但静下心来,对问题进行分解(类似于软件设计),其实你会发现并没那么难

  • 不要过分依赖现有资源,你将来遇到的问题,很难有现成的答案(人生亦如此)。尝试着作为一个新问题来解决

  • 换个思路,久而久之,你会发现大不同,比如咱们操作系统实验

    • 一个思路,实验二信号量同步,先糊弄过去了,懒得深究;到了实验三还是信号量,糊弄起来更困难了;到了课设,说不定还要用到 信号量;考试说不定还会考,你答不上来,你是否会为有这么多机会,一次都没把握住感到后悔?
    • 换个思路,实验二信号量同步,我把信号量弄通了(就算当时没做出来,实验讲解后,掌握了解决问题的思路);到了实验三,按已学的思路来,说不定多半能做出来;这样几次训练下来,对信号量已经很了解了。
    • 你说,人生是不是也大概如此,是不是也要不断迭代呢。
本文系Spark & Shine原创,转载需注明出处本文最近一次修改时间 2022-06-14 18:08

results matching ""

    No results matching ""