进程同步

进程同步

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路由表的并发访问
posted @ 2018-12-06 21:59  pluscat  阅读(507)  评论(0编辑  收藏  举报