zoukankan      html  css  js  c++  java
  • 进程同步

    进程同步

    1.指系统中多个进程中发生的事件存在某种时序关系,需要相互合作,共同完成一项任务
    
    

    生产者/消费者问题

    生产者进程 - 缓冲区 - 消费者进程
    
    1.一个或多个生产者生产某种类型的数据放置在缓冲区中
    2.有消费者从缓冲区中取数据,每次取一项
    3.只能有一个生产者或消费者对缓冲区进行操作
    
    要解决的问题:
    1.当缓冲区已满时,生产者不会继续向其中添加数据
    2.当缓冲区为空时,消费者不会从中移走数据
    
    避免忙等待
    1.睡眠与唤醒操作(原语)
    
    #define N 100
    int count = 0;
    
    void producer(void){
        int item;
        while(TRUE){
            if(count == N) sleep();
            insert_item(item);
            count = count + 1;
            if (count == 1)
              wakeup(consumer)
        }
    }
    
    void consumer(void){
        int item;
        while(TRUE){
            if(count == 0) sleep();
            item = remove_item()
            count = count - 1;
            if(count == N-1)
              wakeup(producer);
              consume_item(item)
        }
    }
    
    //问题,在消费者做sleep()时被cpu切换下cpu消费者此时上CPU,又生产了一个数据,此时唤醒了空生产者,此时CPU切换回消费者,消费者执行sleep,错误产生了
    

    信号量及P,V操作

    1.信号量是一个特殊变量
    2.用于进程间传递信息的整数值
    3.定义如下:
    struc semaphore
    {
        int count;
        queueType queue;
    }
    4.信号量说明:semaphore s;
    5.对信号量可以实施对操作:初始化,P和V(test,increment)
    6.PV操作为原语操作
    
    P(s)
    {
        s.count--;
        if(s.count < 0){
            该进程状态置为阻塞状态;
            将该进程插入相应的等待队列s.queue末尾
            重新调度
        }
    }
    V(s)
    {
        s.count++
        if(s.count <= 0){
            唤醒相应等待队列s.queue中等待的一个进程;
            改变其状态为就绪态,并将其插入就绪队列
        }
    }
    

    用PV操作解决进程间互斥问题

    1.分析并发进程的关键活动,划定临界区
    2.设置信号量mutext,初值为1
    3.在临界区前实施P(mutex)
    4.在临界区之后实施V(mutex)
    
    P1:
    
    P(mutex)
    临界区
    V(mutex)
    -----------
    P2:
    ......
    ......
    P(mutex)
    临界区
    V(mutex)
    ------------
    P3:
    ......
    ......
    ......
    P(mutex)
    临界区
    V(mutex)
    
    //P1首先进入临界区,CPU切换,count此时为-1,P2进入等待队列,CPU切换,count此时为-2,P3进入等待队列,CPU切换到P1,P1完成工作,进行V操作,此时count = -1,将P2加入到就绪队列,CPU切换到P2,P2完成工作,执行V操作,将P3加入到就绪队列
    

    用信号量解决生产者/消费者问题

    #define N 100 //缓冲区个数
    #typedef int semaphore //信号量是一种特殊的整型类型
    #semaphore mutex =1 //互斥信号量,控制对临界区的访问
    #semaphore full = 0 //满缓冲区个数
    void producer(void)
    {
        int item;
        while(TRUE){
            item = produce_item();
            
            P(&empty)
            P(&mutex)
            insert_item(item)
            V(&mutex)
            V(&full)
        }
    }
    void consumer(void){
        int item;
        while(TRUE){
            P(&full);
            P(&mutex)
            item = remove_item()
            V(&mutex)
            V(&empty)
            consume_item(item)
        }
    }
    

    用信号量解决读者/写着问题

    1.多个进程共享一个数据区,读者进程,只读数据,写者进程,只写数据
    
    2.满足条件:
      1.允许过关读者同时执行读操作
      2.不允许多个写着同时操作
      3.不允许读者,写者同时操作
    

    第一类读写者问题:读者优先

    如果读者执行:
    1.无其他读者,写者,该读者可以读
    2.若已有写者等,但又其他读者正在读,则该读者也可以读
    3.若有写者正在写,该读者必须等
    
    如果写者执行:
    1.无其他读者,写者,该读者可以写
    2.若又读者正在读,该写者等待
    3.若又其他写者正在写,该写者等待
    
    
    void render(void)
    
    {
        while(TRUE){
            
            P(mutex) //对rc临界资源做保护
            rc = rc + 1;
            if(rc == 1)P(w) //第一个读者
               读操作
            V(mutex)
               
            P(mutex)
            rc = rc -1;
            if(rc == 0)V(w) //最后一个读者
            V(mutex)
        }
    }
    
    void writer(void)
    {
        while(TRUE){
            ...
            P(w)
              写操作
            V(w)
        }
    }
    

    LINUX提供对读写锁

    1.应用场景
       如果每个执行实体对临界区对访问或者是读或者是写共享变量,但是他们都不会既读又写时,读写锁是最好读选择
    3.实例:linux读IPX路由代码中使用了读写锁,用ipx_routes_lock的读写锁保护IPX路由表的并发访问
    
  • 相关阅读:
    【linux 爱好者群】程序猿的那些聊天记录
    开发技巧记录
    tcmalloc 内存分析
    mktime很慢就自己去实现一个吧
    bash变量常用技巧
    文本处理sed常用操作
    【TED】如何掌握你的自由时间
    vim粘贴代码问题
    工作方式的反思-20170319
    【one day one linux】find 用法详解小记
  • 原文地址:https://www.cnblogs.com/pluslius/p/10079872.html
Copyright © 2011-2022 走看看