MUTEX进程同步 - 为什么常见的锁变量不起作用?

时间:2015-09-02 16:04:34

标签: multithreading parallel-processing mutex

在我的大学幻灯片中,老师写道,这个MUTEX问题的解决方案不起作用。为什么呢?

lock = true表示关键部分已有进程

  1. Process1检查锁定并看到它为假
  2. Process2中断Process1
  3. Process2检查锁定并且仍为false
  4. Process2将lock设置为true并进入关键部分
  5. Process1 CHECKS锁定AGAIN,将其设置为true并进入临界区。 (怎么样?为什么它不是真的,所以它不能进入​​?)

1 个答案:

答案 0 :(得分:0)

假设你的'lock'变量只是一个变量,那么检查变量值然后有条件地设置该变量的代码可以是多个指令。

考虑以下psuedocode实现:

  • 将'锁定'读入寄存器A
  • 将寄存器A与零
  • 进行比较
  • 如果比较为假,请跳到最后
  • 将'1'写入'已锁定'。

例如,请在C#中考虑此代码:

public static class Program
{
    private static int locked = 0;

    private static bool GetLock()
    {
        if( locked == 0 )
        {
            locked = 1;
            return true;
        }
        else
        {
            return false;
        }
    }
}

考虑它的反汇编:

            if( locked == 0 )
00000000  cmp         dword ptr [0003E4F0h],0 
00000007  jne         0000000000000019 
            {
                locked = 1;
00000009  mov         dword ptr [0003E4F0h],1 
                return true;
00000013  mov         eax,1 
00000018  ret 
            }
            else
            {
                return false;
00000019  xor         eax,eax 
0000001b  ret 

现在考虑当两个线程同时尝试执行此操作时会发生什么:

  • 线程1:读取'已锁定'为0,输入'if'语句。
  • OS线程调度程序决定更改CPU上的哪个线程
  • OS将线程2放在CPU上。
  • 线程2:读取'已锁定'为0,输入'if'语句
  • 线程2:将'1'写入'locked'表示已获取它。
  • 线程2:返回true表示已获取它。
  • OS线程调度程序决定更改CPU上的哪个线程
  • OS将线程1放在CPU上。
  • 线程1:已经在'if'语句中,因此它执行下一条指令
  • 线程1:将'1'写入'locked'以表示它已获取它
    • 但是woops,变量已经设置为1,因为有人获得了它。
  • 线程1:返回true表示它认为它获得了锁定(它没有)。

现在无论线程1和线程2正在做什么工作(可能更新内存中的帐户余额)都会相互覆盖。如果这两个线程试图发布两个事务 - 添加1000,并删除500 - 这就是现在他们没有独占访问权会发生的事情:

  • 主题1:从帐户余额中读取“1000”。
  • 主题2:从帐户余额中读取“1000”。
  • 主题1:计算新余额1000 + 1000 = 2000。
  • 线程2:计算新余额1000 - 500 = 500。
  • 线程1:将新余额2000写入内存。
  • 线程2:将新余额500写入内存。

现在由于线程错误,我的帐户余额缺少1000美元。