设为首页 加入收藏

TOP

【操作系统】经典的同步问题(生产者消费者问题, 哲学家进餐问题, 读写问题)(一)
2017-10-11 14:59:27 】 浏览:9235
Tags:操作系统 经典 同步 问题 生产者 消费者 哲学家 进餐 读写

用专业术语来说, 进程是程序的一次动态执行.说简单点, 就是进程是系统中的某个任务.操作系统中有多个任务需要执行, 那么怎样执行才能使它们同步呢? 即如何让任务并发执行互不影响呢? 这就引出了进程同步中的经典问题: 生产者消费者问题, 哲学家进餐问题, 读写问题

 

生产者-消费者问题

有一群生产者进程在生产产品, 并将这些产品提供给消费者进程取消费. 为使生产者进程与消费者进程能并发进行, 在两者间设置了一个具有n个缓冲区的缓冲池, 生产者进程将其所生产的产品翻入缓冲区中, 消费者进程可从一个缓冲区中取走产品取消费.生产者消费者进程都以异步方式进行, 但它们之间必须保持同步, 不允许消费者进程到空缓冲区去取产品, 也不允许生产者进程向已满的缓冲区投放产品.

一个缓冲池中有n个缓冲区, 只要缓冲池未满, 生产者便可以投放产品; 缓冲池为空, 消费者便可以消费产品

法一:记录型信号量

//生产者消费者问题
//记录型信号量
//缓冲池中有n个缓冲区, 互斥信号量mutex, 
//信号量empty表示空缓冲区数量, full表示满缓冲区的数量
int in = out = 0;
item buffer[n];
semaphore mutex = 1, empty = n, full = 0;
void producer() {
    do {
        producer an item nextp;
        wait(empty);
        wait(mutex);
        buffer[in] = nextp;
        in = (in + 1) % n;
        signal(mutex);
        signal(full);
    } while(true);
}
void consumer() {
    do {
        wait(full);
        wait(mutex);
        nextc = buffer[out];
        out = (out + 1) % n;
        signal(mutex);
        signal(empty);
        consumer the item in nextc;
    } while(true);
}
void main() {
    cobegin
        producer();
        consumer();
    coend
}

注意: 对信号量的wait()和signal()操作必定是成对出现的.

法二:AND型信号量

//AND型信号量
//Swait(empty, mutex)代替wait(empty)和wait(mutex)
//Ssignal(mutex,full)代替signal(mutext)和signal(full)
//Swait(full, mutex)代替wait(full)和wait(mutex)
//Ssignal(mutex, empty)代替signal(mutex)和signal(empty)
int in = out = 0;
item buffer[n];
semaphore mutex = 1, empty = n, full = 0;
void producer() {
    do {
        producer an item nextp;
        Swait(empty, mutex);
        buffer[in] = nextp;
        in = (in + 1) % n;
        Ssignal(mutex, full);
    } while(true);
}
void consumer() {
    do {
        Swait(full, mutex);
        nextc = buffer[out];
        out = (out + 1) % n;
        Ssignal(mutex, empty);
        consumer the item in nextc;
    } while(true);
}
void main() {
    cobegin
        producer();
        consumer();
    coend
}

 

法三: 管程

//管程
//建立管程producerconsumer,PC
/*
put(x), 生产者利用该过程将自己生产的产品投放到缓冲池中, 并用整型变量count表示缓冲池中已有的产品数目,当
count>=N时, 表示缓冲池已满,生产者需等待.
get(x), 消费者利用该过程从缓冲池中取出一个产品, 当count<=0时, 表示缓冲池已无可用的产品, 消费者需等待
condition 为notfull和notempty
cwait(condition), 当管程被一个进程占用时, 其他进程调用该进程时阻塞, 并挂在条件condition的队列上
csignal(condition), 唤醒在cwait执行后阻塞在条件condition队列上的进程, 如果这样的进程不止一个, 则选择其中一个
实施唤醒操作, 如果队列为空, 则无操作而返回.
*/
Monitor producerconsumer {
    item buffer[N];
    int in, out;
    condition notfull, notempty;
    int count;
    public:
        void put(item x) {
            if (count >= N) cwait(notfull);
            buffer[in] = x;
            in = (in + 1) % N;
            count++;
            ssignal(notempty);
        }
        void get(item x) {
            if (count <= 0) cwait(notempty);
            x = buffer[out];
            out = (out + 1) % N;
            count--;
            csignal(notfull);
        }
        {
            in = 0;
            out = 0;
            count = 0;
        }
}PC;

void producer() {
    item x;
    while (true) {
        producer an item in nextp;
        PC.put(x);
    }
}
void consumer() {
    item x;
    while (true) {
        PC.get(x);
        consumer the item in nextc;
    }
}
void main() {
    cobegin
        producer();
        consumer();
    coend
}

 

哲学家进餐问题

五个哲学家公用一张圆桌, 分别坐在周围的五张桌子上, 在圆桌上有五个碗和五只筷子交叉排列, 它们的生活方式是交替的进行思考和进餐. 哲学家进行思考时不用筷子, 饥饿时取一只他两边的任意一只筷子(默认取左边的筷子, 没有时取右边的, 都没有时就取不了), 当他有两只筷子时就能进餐. 进餐后, 放下筷子继续思考.若只有一只筷子, 不放弃该筷子并等待拥有另一只筷子时再进餐.

用一个信号量表示一只筷子, 共五个信号量 semaphore chopsitck[5] = {1, 1, 1, 1, 1}; , 为 1 表示筷子未拿起, 为0表示筷子被拿起.那么第i为科学家的进餐活动就可以描述为

法一:记录型信号量

do {
    wait(chopstick[i]);
    wait(chopstick[(i + 1) % 5]);
    //eat
    signal(chopstick[i]);
    signal(chopstick[(i + 1) % 5]);
    //think
} while (true);

假设五位哲学家都要拿筷

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇2016款MACBOOK PRO触控条版 安装W.. 下一篇mac终端命令

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目