现在的位置: 首页 > 综合 > 正文

p,v操作例题解析–读者-写者问题–誊抄问题——睡眠理发师问题

2013年08月12日 ⁄ 综合 ⁄ 共 2357字 ⁄ 字号 评论关闭

问题1:读者写者问题

层次1:只有读者,最多允许有k个读者,用p,v操作写出程序。

int main()
{
    int rspace = k;
    cobegin
        read_1();
        read_2();
        ……
        read_n();
    coend
}

read_i()
{
    p(rspace);
    ……
    v(rspace);
}

这个操作,需要设置信号灯rspace来控制是否达到了k个人数,当达到k个人数的时候rspace == 0,这个时候需要挂起。

层次2:一个读者,一个写者问题。

int main()
{
    int mutex = 1;
    cobegin
        read_i();
        write_i();
    coend
}

read_i()//i = 1, 2, ……
{
    p(mutex);
    ……
    v(mutex);
}

write()//i = 1, 2,  ……
{
    p(mutex);
    ……
    v(mutex);
}

这是一个临界资源,对于临界资源,需要设置信号灯mutex控制只有一个进程可以访问。

层次3:有多名读者,有多名写者。

int main()
{
    int mutex = 1;//这个是读和写的互斥
    int mutex1 = 1;//这个是保护cnt等变量
    cobegin
        read_i();
        write_i();
    coend
}

read_i()//i = 1, 2, ……
{
    p(mutex1);
    cnt ++;
    if(cnt == 1)
    {
        p(mutex);
    }
    v(mutex1);
    ……
    p(mutex1);
    cnt --;
    if(cnt == 0)
    {
        v(mutex);
    }
    v(mutex1);
}

write()//i = 1, 2, ……
{
    p(mutex);
    ……
    v(mutex);
}

这个资源,mutex把读和写的互斥,用mutex1把cnt临界资源保护起来。//问题:那么mutex本身不需要保护吗?怎么保证不会同时去修改mutex的值?

层次4:有多名读者,至多k名读者,有多名写者。

int main()
{
    int mutex = 1;//这个是读和写的互斥
    int mutex1 = 1;//这个是保护cnt等变量
    int cnt = 0;
    int rspace = k;
    cobegin
        read_i();
        write_i();
    coend
}

read_i()//i = 1, 2, ……
{
    p(mutex1);
    p(rspace);
    cnt ++;
    if(cnt == 1)
    {
        p(mutex);
    }
    v(mutex1);
    ……
    p(mutex1);
    cnt --;
    if(cnt == 0)
    {
        v(mutex);
    }
    v(rspace);
    v(mutex1);
}

write()//i = 1, 2, ……
{
    p(mutex);
    ……
    v(mutex);
}

这个需要rspace = k这个来保证,也就是说当临界值的时候,就是rspace  = 0 的时候就是临界值。

问题2:誊抄问题

问题由来:

由于打印机,和卡带机(以前的输入设备)的输入比较慢,如果一个输入一个输出速度比较慢,所以设立了两个缓冲区,可以讲时间缩短。

设原来时间:输入一个字符T1,打印一个字符T2,那么一个字符从输入到输出总共时间T1 + T2,优化后时间是max(T1 + T2);

//输入f,输出g
int main()
{
    get(s, t);
    while(誊抄未完)
    {
        t = s;
        cobegin
            get(s, f);
            put(t, g);
        coend
    }
}

这个题目的关键在于:

1. 首先要get(s, t)保证一开始的时候s缓冲区中有需要被使用的内容,t缓冲区中的内容不被使用。

2. t = s是一个赋值操作,速度极快,忽略不计,因此时间取决于max(T1 + T2);

题目要求:

n理发店里有一位理发师、一把理发椅和n把供等候理发的顾客休息的椅子;如果没有顾客,理发师便在理发椅上睡觉,当有顾客到来时,他唤醒理发师;如果理发师正在理发时又有新的顾客来到,那么如果还有空椅子,顾客就坐下来等待,否则就离开理发店。
步骤一:
barber:如果有顾客就理发,没有顾客就不理发。临界条件是有没有顾客,因此定义顾客数cnt = 0;
custermer:如果有空位置就坐在空位置,如果没有空位置就走开,不存在等空位置的状态,因此只存在判断语句,没有临界值。
int main()
{
    int cnt = 0;//顾客的个数
        cobegin
            barber();
            customer();
        coend
}

barber()
{
    while(1)
    {
        p(cnt);
        ……
    }
}

customer_i()//1,2,……
{
    if(cnt < n + 1) v(cnt);
}

问题:这个时候的cnt是存在于customer 和 barber共同之中的,因此可能出现custermer 和 barber 共同改变 cnt的情况,所以说需要设置一个变量mutex保护cnt这个变量的互斥操作。

步骤二:
int main()
{
    int cnt = 0;//顾客的个数
    int mutex = 0;
        cobegin
            barber();
            customer();
        coend
}

barber()
{
    while(1)
    {
        p(mutex);
        p(cnt);
        v(mutex);
        ……
    }
}

customer_i()//1,2,……
{
    p(mutex);
    if(cnt < n + 1) v(cnt);
    v(mutex);
}
问题2:
/*对于每个custemer来说,整个程序应该是一个互相通信的过程,custermer -> barber -> custermer完成。理发完之后custermer才可以杀死进程,而不可以申请完立即杀死进程。所以存在一个等待barber 的通信变量。*/
对于这个问题,我们先看一下p操作和v操作的工作原理。
p(k)操作:如果 k > 1,那么就索要操作成功,如果k < 1,那么索要操作失败,同时把k的值减小1,把该进程挂在到k的wait队列中去。
v(k)操作:释放k所代表的一个资源,如果k < 0,(假设k = -m,那么m就代表等待队列中的进程个数)那么同时取出wait等待队列中的一个进程继续进行。
简而言之,p操作是申请资源,v操作是释放资源。
未完待续。

抱歉!评论已关闭.