不使用系统API来实现互斥保护功能

来源:互联网 发布:telnet linux 安装 编辑:程序博客网 时间:2024/05/18 04:00

一般临界资源的互斥保护,需要使用类似take_mutex / give_mutex 类似的系统API来实现,

一般需要从用户空间切换到内核空间,有时候可能要关中断等,为了实现一个开销小的,

实现简单的临界资源的互斥保护机制,我设计了一个方法,希望大家能参考一下,给点建议。

volatile int a = 0;

volatile int b = 0;

/*  线程 A */

void thread_A()
{
     while ( 1 ) {
     a++;
     if ( b == 0 ) {
          access_the_critical_resource;
          a = 0;
          break;
     } else {
         a = 0;
     }
    }
}

/*  线程 B */


void thread_B()
{
     while ( 1 ) {
     b++;
     if ( a == 0 ) {
          access_the_critical_resource;
          b = 0;
          break;
     } else {
         b = 0;
     }
    }
}

现在来分析一下为什么这两个线程能实现互斥,

A线程首先将a加1,然后去加查b变量,如果b为0,说明B线程还没有将b加1,或者是B线程已经将b加1,但还没有写回到内存。总之B线程还运行在b++语句之前的某个位置,或者是刚执行完b=0的操作(即运行在b=0与b++之间的某个位置),所以我们断定B此时没有进入临界区,故A线程可以执行后面的临界区访问操作。

那么如果但A线程检查b变量时,如果b变量不等于0,那么此时B线程有可能在访问临界区,也有可能只是执行完了b++语句,但还没有进入临界区,此时A线程通过if ( b == 0 )的判断来避免了与B同时进入临界区的危险。

再分析,因为A线程在尝试进入临界区之前会将自己的开关变量a加1,所以一旦A互斥检查获得通过的话(if ( b == 0 )),就说明自己可以放心进入临界区了,因为此时可以肯定对方运行在b = 0;

与 b++;这两条语句之间,而不是b++与b=0之间(请注意这两条语句的先后顺序),所以当A进入了临界区,并处在临界区的这段时间内,B会被 if ( a == 0 )这个条件阻挡在临界区外,直到A出了临界区,执行a=0;break;,

此时B才有可能进入到临界区。

根据对称性,把A和 B反过来分析也一样,当然这种方法有很多缺点,比如极端情况下两个线程有可能都进不了

临界区等,我这里就不一一列举了,仅仅做个试验尝试而已。

 在SMP的环境中,这种方法应该也可以,不会有逻辑错误。 

原创粉丝点击