【问题标题】:Why to use mutex instead of boolean variable for thread synchronization?为什么要使用互斥锁而不是布尔变量进行线程同步?
【发布时间】:2013-10-23 06:11:49
【问题描述】:

我正在尝试理解 C 中的多线程编程。

我怀疑既然我们使用 MUTEXES 进行线程同步,为什么我们不能使用布尔变量来阻塞要执行的代码的关键区域。

相对于布尔变量,静音的特点是什么?

PS:其实这个问题是在采访中被问到的。 因此,请分享您对此的了解。

【问题讨论】:

  • 这是关于任何特定语言的问题吗?您没有得到与语言无关的答案。

标签: multithreading synchronization boolean mutex


【解决方案1】:

问题是两个线程都可以同时看到布尔值可用,然后都认为继续是安全的。

例如,假设您有以下代码:

bool myLock = false;  // visible to all threads

void someFunction()
{
    if (!myLock)
    {
        myLock = true;
        // do whatever
        // and then release the lock
        mylock = false;
    }
}

现在,假设有两个线程正在执行。线程 A 读取 myLock 并看到它是 false,因此它继续执行下一条指令。同时,线程 B 读取 myLock 并看到它是 false,因为线程 A 尚未将其设置为 true。所以线程 B 继续前进,也获得了锁。此时,两个线程都在执行本应受互斥锁保护的代码。

它变得更糟,因为线程 A 完成了它正在做的事情并将mylock 设置回false,而线程 B 仍在执行。因此,即使线程 B 仍在其中,另一个线程也可以出现并获取锁。

互斥体保证原子性。也就是说,它保证检查和更新一次只能由一个线程完成。所以如果你用互斥体替换布尔值,你有:

if (mutex.Acquire())
{
    // do stuff
    // then release the lock
    mutex.Release();
}

两个线程不可能同时获取互斥锁。

【讨论】:

  • "检查和更新一次只能由一个线程完成。"深入细节,这是否意味着可以进行检查,并且存在上下文切换,但其他线程知道存在检查和更新,因此他们不会尝试?换句话说,我要问的是,互斥锁是如何工作的,它是自然原子的还是通过知道只有线程可以进行检查和更新并且可以检查另一个线程进入并更新来工作,而在另一个线程中它知道检查和更新正在进行中,所以不能这样做吗?
  • 互斥体自然是原子的。它使用执行原子检查和更新的 CPU 指令。因此,如果一个线程开始获取互斥锁,另一个线程就不可能这样做了。
【解决方案2】:

如果您尝试将布尔值用作“假互斥锁”,我可以很容易地指出您的实现中的缺陷,直到您基本上重新发明互斥锁为止。互斥体基本上是一个布尔值,包含用于线程同步所需的所有额外内容。

【讨论】:

    【解决方案3】:
    int locked = 0;
    void lock( void ) {
        while ( locked ) sleep_api( little );
        locked = 1;
        return;
    }
    

    这段代码是错误的,因为两个线程可以同时看到locked变量中的0,并认为他们有锁。

    【讨论】:

    • 很好的例子。如果只有一个线程将写入布尔值而另一个线程将是唯一从布尔值读取的线程怎么办?那会安全吗?
    • 视情况而定。布尔值是什么意思,线程在做什么,取决于布尔值?
    【解决方案4】:

    首先,您的建议并不完全清楚。假设您有五个线程都在竞争相同的资源。很清楚您将如何使用互斥锁来确保独占访问。目前还不清楚如何为此使用布尔变量。

    也就是说,布尔变量有时可用于同步。但是,这适用的情况有限,并且有一些注意事项(例如,此类变量通常需要声明为volatile)。

    互斥锁的应用范围更广。可能值得一提的是,除了(正确地)确保只有一个线程可以进入受保护部分之外,它们还充当memory barriers

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 1970-01-01
      • 1970-01-01
      • 2013-06-07
      • 1970-01-01
      • 2012-06-30
      • 2016-06-21
      相关资源
      最近更新 更多