通过硬件的支持实现互斥

一、中断禁用

   单处理机:在单处理机中,并发进程不能重叠,只能交替,操作系统通过中断来实现进程的交替,那么就会存在一个问题,当一个进程A运行到临界区时发生了中断,另一个进程B运行,进程B也可以运行临界区代码,这样就改变了临界资源,当进程A再接着中断的位置运行时相关数据有可能已经被进程B修改,出现错误。

      这个问题可以通过禁用中断来解决,禁用中断和启用中断都是原语操作。通过这个方法来实现互斥如下:

while(true)
{
    /* 禁用中断 */
    /* 临界区 */
    /* 启用中断 */
    /* 其余部分 */
}

 中断禁用的优缺点:

优点:临界区不可被中断,故此可以保证互斥

缺点:由于处理器被限制于只能交替执行程序,因此执行的效率有明显的降低 

二、专用机器指令  

  多处理机:在多处理机配置中,几个处理器共享内存,处理器间的行为是对等的,处理器之间没有支持互斥的中断机制。在硬件级别上,对存储单元的访问排斥对相同单元的其他访问。基于这一点,处理器的设计者提出了一些机器指令,用于保证两个动作的原子性,即某一时刻只能有一个临界区代码访问临界资源。两种最常见的指令是:比较和交换指令交换指令

  • 比较和交换指令如下:
int compare_and_swap(int *word, int testval, int newval)
{
    int oldval;
    oldval = *word;
    if(oldval == testval) *word = newval;
    return oldval;
}

示例:

const int n = /* 进程个数 */
int bolt;
void p(int i)
{
    while(true)
    {
        while(compare_and_swap(bolt, 0, 1) == 1)
        {
            /* 不做任何事 */
        }
        /* 临界区 */
        bolt = 0;
        /* 其余部分 */
    }
}

void main()
{
    bolt = 0;
    parbegin (p(1), p(2), ... ,p(n));
}

    进程开始,bolt = 0当某一个进程A率先执行比较和交换指令时可以通过,通过之后便将bolt改为1,而测试值是0,因此其他进程执行比较和交换指令时不能通过,处于忙等待状态(在进程得到临界区访问权之前,它只能继续执行测试变量的指令来得到访问权,除此之外不能做其他事情),当进程A执行完临界区之后又将bolt值改为0, 则将会有一个进程测试通过,往复执行,即可保证某一时刻只有一个临界区代码访问临界资源。

  • 交换指令如下:
void exchange(int *register, int *memory)
{
    int temp;
    temp = *memory;
    *memory = *register;
    *register = temp;
}

示例:

int const n = /* 进程个数 */;
int bolt;
void p(int i)
{
    int keyi = 1;
    while(true)
    {
        do exchange(&keyi, &bolt)
        while(keyi != 0)
        {
            /* 临界区 */
        }
        bolt = 0;
        /* 其他部分 */
    }
}

void main()
{
    bolt = 0;
    parbegin (p(1), p(2), ... ,p(n));
}

     进程开始,bolt = 0当某一个进程A率先执行交换指令时可以通过,通过之后便将bolt改为1,因此其他进程执行交换指令时bolt = 1,通过交换将keyi置为1,则将一直处于while循环中,无法执行下边临界区。当进程A执行完临界区之后又将bolt值改为0, 则将会有一个进程测试通过,往复执行,即可保证某一时刻只有一个临界区代码访问临界资源。

机器指令方法的优缺点:

优点

  • 适用于在单处理器或共享内存的多处理器上的任何数目的进程
  • 非常简单且易于证明
  • 可用于支持多个临界区,每个临界区可以用它自己的变量定义

缺点

  • 使用了忙等待:因此当一个进程正在等待进入临界区时,它会继续消耗处理器时间
  • 可能饥饿:当一个进程离开一个临界区并且有多个进程正在等待时,选择哪一个进程是任意的,因此某些进程可能被无限拒绝进入。
  • 可能死锁:当某个进程通过专门指令时,在临界区中发生中断将有可能发生死锁。
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
互斥锁(Mutex)是一种用于多线程编程中保护共享资源的同步机制。它提供了互斥访问的能力,以防止多个线程同时访问共享资源而导致的数据不一致或竞态条件等问题。 在底层实现上,互斥锁通常使用特定的硬件指令或操作系统提供的原子操作来实现。这些原子操作可以确保对共享资源的访问是原子的,即在任何时刻只能有一个线程获得互斥锁的所有权。 一种常见的实现方式是使用原子操作的比较并交换(Compare and Swap,CAS)指令。该指令可以比较内存中的值与预期值是否相等,如果相等则将新值写入内存,并返回操作前的值;如果不相等,则不做任何修改并返回当前值。利用CAS指令,可以实现一个简单的自旋锁。 自旋锁是一种忙等待的锁,当一个线程尝试获取互斥锁但未成功时,它会反复检查互斥锁的状态直到成功获取为止。这种方式避免了线程切换的开销,适用于短暂的争用情况。 除了自旋锁,还有其他形式的互斥实现,如基于信号量、互斥体等。这些实现方式依赖于操作系统的支持,通过系统调用来实现对锁的操作。 总的来说,互斥锁的底层实现通常依赖于硬件指令或操作系统提供的原子操作,以确保对共享资源的访问是原子的,并通过自旋等方式提供线程之间的同步机制。具体的实现方式可能因操作系统或硬件平台而异。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值