我正在尝试理解C中的多线程编程。
我怀疑由于我们使用MUTEXES进行线程同步,为什么我们不能使用布尔变量来阻止要执行的代码的关键区域。
布尔变量的静音特性是什么?
PS:实际上这个问题在接受采访时被问到了。 所以请分享您对此的了解。答案 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)
如果你试图使用布尔值作为“假互斥体”,我可以很容易地指出你的实现中的缺陷,直到你基本上重新发明互斥锁。互斥体基本上是一个布尔值,包含使用它进行线程同步所需的所有额外内容。