多进程临界区算法

373 阅读2分钟

临界区必备要素

  1. 互斥进入:一次仅允许一个进程进入;在任何时候,一旦已经有进程进入临界区,其它试图进入临界区的进程必须等待。
  2. 有空让进:如果没有进程处于临界区内,且有进程请求进入临界区,则应该能让某个请求的进程进入临界区执行。即不发生资源死锁的情况。
  3. 有限等待:一个进程提出进入临界区的请求后,最多需要等待临界区被使用有限次以后,该进程就可以进入临界区。这样,任何一个进程对临界区的等待时间都是有限的,即不出现因等待临界区而造成的饿死情况。

适用两进程的Peterson算法

#define true    1
#define false   0
int lock;
int hold [2]={false};

void enter_lock(int thread_id)
{
    hold[thread_id]=true;/*标记占有资源*/
    lock=thread_id;//存在hold标记都为true的可能,所以需要turn
    while(lock==thread_id&&(hold[1-thread_id]==true));/*阻塞,等待调度*/
}

void exit_lock(int thread_id)
{
    hold[thread_id]=false;/*标记释放资源*/
}

void process_0(void)//线程0
{
    enter_lock(0);
    //临界区
    //访问资源
    exit_lock(0);
}
void process_1(void)//线程1
{
    enter_lock(1);
    //临界区
    //访问资源
    exit_lock(1);
}

适用多进程的Lamport面包店算法

#define true    1
#define false   0
#define process_num 4//线程数目
int choosing[process_num]={false};
int number[process_num]={0};

int find_max(void)/*找出最大号码*/
{
    int max=0;
    int i=0;
    for(;i<process_num;++i)
    {
        if(number[i]>max)
            max=number[i];
    }
    return max;
}

void enter_lock(int thread_id)
{
    int i=0;
    choosing[thread_id]=true;
    number[thread_id]=find_max()+1;/*选号码, 存在两个进程都进入此段选择相同号码的可能*/
    choosing[thread_id]=false;
    for(;i<process_num;++i)
    {
        while(choosing[i]);/*等待其他线程选号码*/
        /*存在同号的可能,此时用进程号区分。while表示阻塞,等待调度*/
        while((number[i] != 0)&&
             ((number[i] < number[thread_id]) || ((number[i] == number[thread_id])&&(i < thread_id))));
    }
}

void exit_lock(int thread_id)
{
    number[thread_id]=0;/*释放号码*/
}

void process_A(void)//线程0
{
    enter_lock(1);
    //临界区
    //访问资源
    exit_lock(1);
}
void process_B(void)//线程1
{
    enter_lock(2);
    //临界区
    //访问资源
    exit_lock(2);
}