进程同步:问题的解决,原语

在出现了同步问题后,如何解决呢?可以在访问公共变量的时候,设置一个锁变量,这个锁变量有两个状态,一个是上锁的状态,另一个是释放状态,如果锁变量没有上锁,则可以访问变量,同时将锁置为上锁状态。待访问变量结束后,将锁置为释放状态,允许下一个进程访问变量。示例的程序如下:

int     lock = 0;
int     cnt = 0;

int     app1(void)
{
    int     tmp;
    
    while(lock) ;
    lock = 1;
    
    printf("app1 count:%d\n",cnt);
    tmp = cnt + 1;
    Proc_delay(100);
    printf("app1 count:%d\n",tmp);
    cnt = tmp;
    
    lock = 0;
    
    return 0;
}

int     app2(void)
{
    int     tmp;
    
    while(lock) ;
    lock = 1;
    
    printf("app2 count:%d\n",cnt);
    tmp = cnt + 1;
    Proc_delay(100);
    printf("app2 count:%d\n",tmp);
    cnt = tmp;
    
    lock = 0;
    
    return 0;
}

修改为这样后,就可以得到想要的结果了,但是,这还是存在隐患,因为

while(lock) ;
    lock = 1;


这段代码有两个问题,

1、这实际上还是存在被打断的可能,虽然从检测到赋值间隔很短,但其仍是需要几条机器指令才能完成的。

2、这处于一个忙等待的状态,如果不能保证其他程序占有锁的时间很短,则会造成CPU时间浪费在循环检测下。


为了解决这两个问题,就提出了一个概念,就是需要在检测到锁空闲,然后赋值这两步保证不被打断。这种不能被打断的多步连续操作,称为原子操作,一般的操作系统将其称为原语。在单CPU,在现在要说单cpu单核心,的情况下,可以通过关中断来实现,因为在关闭中断后,除非进程自行放弃CPU,是不可能被打断的。

根据这一概念,Lenix实现了锁操作

void        Proc_sleep(void)
{
    proc_current->proc_stat = PROC_STAT_SLEEP;
    Proc_sched();
}

void        Proc_wakeup(void)
{
    int i;
    Disable_irq();
    for( i = 1 ; i < PROC_MAX ; i++)
    {
        if( PROC_STAT_SLEEP == proc_pool[i].proc_stat )
            proc_pool[i].proc_stat = PROC_STAT_RUN;
    }
    Enable_irq();
}

void        Lck_lock(lock_t * lck)
{
    Disable_irq();

    while( *lck )
        Proc_sleep();
    *lck = 1;
    
    Enable_irq();
}

void        Lck_free(lock_t * lck)
{
    *lck = 0;
    Proc_wakeup();
}


锁的实现要依靠进程状态转换操作支持,在Lck_lock中没有转入睡眠,由于关了中断,就变成死循环了。有了锁机制之后,原先的代码就变成一下的样子

int     lock = 0;
int     cnt = 0;

int     app1(void)
{
    int     tmp;
    
    Lck_lock(&lock);    
    
    printf("app1 count:%d\n",cnt);
    tmp = cnt + 1;
    Proc_delay(100);
    printf("app1 count:%d\n",tmp);
    cnt = tmp;
    
    Lck_free(&lock);    
    
    return 0;
}

int     app2(void)
{
    int     tmp;
    
    Lck_lock(&lock);    
    
    printf("app2 count:%d\n",cnt);
    tmp = cnt + 1;
    Proc_delay(100);
    printf("app2 count:%d\n",tmp);
    cnt = tmp;
    
    Lck_free(&lock);    
    
    return 0;
}


嗯,这个代码看起来比较规范了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值