MUTEX 进程同步 - 为什么公共锁变量不起作用?
MUTEX process synchronization - why does common lock variable not work?
在我的大学 powerpoint 幻灯片中,老师写道,这个 MUTEX 问题的解决方案不起作用。为什么?
lock = true表示临界区已经有进程
- Process1 检查锁并发现它是假的
- Process2 中断 Process1
- Process2 检查锁,它仍然是 false
- 进程2设置lock为true并进入临界区
- 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 美元。
在我的大学 powerpoint 幻灯片中,老师写道,这个 MUTEX 问题的解决方案不起作用。为什么?
lock = true表示临界区已经有进程
- Process1 检查锁并发现它是假的
- Process2 中断 Process1
- Process2 检查锁,它仍然是 false
- 进程2设置lock为true并进入临界区
- 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 美元。