为什么要使用互斥锁而不是布尔变量进行线程同步?

时间:2013-10-23 06:11:49

标签: multithreading synchronization boolean mutex

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

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

布尔变量的静音特性是什么?

PS:实际上这个问题在接受采访时被问到了。 所以请分享您对此的了解。

4 个答案:

答案 0 :(得分:7)

问题是两个线程都可以同时看到布尔值,并且两者都会认为可以继续安全。

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

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完成了它正在做的事情,并且在线程B仍在执行时将mylock设置回false。因此,即使线程B仍在那里,另一个线程也可以出现并锁定。

互斥锁保证原子性。也就是说,它保证了检查和更新一次只能由一个线程完成。因此,如果使用互斥锁替换布尔值,则可以:

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

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

答案 1 :(得分:2)

int locked = 0;
void lock( void ) {
    while ( locked ) sleep_api( little );
    locked = 1;
    return;
}

此代码错误,因为两个线程可以同时在锁定变量中看到0,并认为它们具有锁定。

答案 2 :(得分:1)

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

也就是说,布尔变量有时可用于同步。但是,这种情况适用的情况有限,并且有一些警告(例如,通常需要声明这些变量volatile)。

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

答案 3 :(得分:1)

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