MUTEX 进程同步 - 为什么公共锁变量不起作用?

MUTEX process synchronization - why does common lock variable not work?

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

lock = true表示临界区已经有进程

  1. Process1 检查锁并发现它是假的
  2. Process2 中断 Process1
  3. Process2 检查锁,它仍然是 false
  4. 进程2设置lock为true并进入临界区
  5. Process1 CHECKS lock AGAIN,将其设置为true并进入临界区。 (怎么?为什么读的不是真的,所以进不去?)

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

考虑以下伪代码实现:

  • 将'locked'读入寄存器A
  • 将寄存器 A 与零进行比较
  • 如果比较为假,则跳到最后
  • 将“1”写入'locked'。

例如,在 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:读到'locked'为0,进入'if'语句
  • OS 线程调度程序决定更改 CPU
  • 上的线程
  • OS 将线程 2 放在 CPU.
  • 线程2:读到'locked'为0,进入'if'语句
  • 线程 2:将“1”写入 'locked' 以指示它已获取它。
  • 线程 2:returns true 表明它获得了它。
  • OS 线程调度程序决定更改 CPU
  • 上的线程
  • OS 将线程 1 放在 CPU.
  • 线程1:已经在'if'语句中,所以它执行下一条指令
  • 线程 1:将“1”写入 'locked' 以指示它已获取它
    • 但是糟糕,该变量已经设置为 1,因为其他人获取了它。
  • 线程 1:returns true 表明它认为它获得了锁(它没有)。

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

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

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