我试图理解 C 中的多线程编程。
我怀疑当我们使用 MUTEXES 进行线程同步时,为什么我们不能使用布尔变量来阻止要执行的代码的关键区域。
布尔变量静音的特点是什么?
PS:其实这个问题是在面试的时候问的。因此,请分享您对此的了解。
我试图理解 C 中的多线程编程。
我怀疑当我们使用 MUTEXES 进行线程同步时,为什么我们不能使用布尔变量来阻止要执行的代码的关键区域。
布尔变量静音的特点是什么?
PS:其实这个问题是在面试的时候问的。因此,请分享您对此的了解。
问题是两个线程都可以同时看到布尔值可用,然后都认为继续是安全的。
例如,假设您有以下代码:
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 继续前进,也获得了锁。此时,两个线程都在执行本应受互斥锁保护的代码。
It gets worse because Thread A finishes what it's doing and sets mylock
back to false
while Thread B is still executing. So another thread can come along and take the lock even though Thread B is still in there.
A mutex guarantees atomicity. That is, it guarantees that the check-and-update can only be done by a single thread at a time. So if you replace the boolean with a mutex, you have:
if (mutex.Acquire())
{
// do stuff
// then release the lock
mutex.Release();
}
There's no chance that two threads can acquire the mutex simultaneously.
如果您尝试将布尔值用作“假互斥锁”,我可以很容易地指出您的实现中的缺陷,直到您基本上重新发明互斥锁为止。互斥锁基本上是一个布尔值,其中包含用于线程同步所需的所有额外内容。
int locked = 0;
void lock( void ) {
while ( locked ) sleep_api( little );
locked = 1;
return;
}
这段代码是错误的,因为两个线程可以同时看到locked变量中的0,并认为他们拥有了锁。
首先,你的建议并不完全清楚。假设您有五个线程都在竞争相同的资源。很清楚您将如何使用互斥锁来确保独占访问。目前还不清楚如何为此使用布尔变量。
也就是说,布尔变量有时可用于同步。但是,这适用的情况是有限的,并且有一些警告(例如,这些变量通常需要声明volatile
)。
互斥锁的应用范围更广。可能值得一提的是,除了(正确地)确保只有一个线程可以进入受保护部分之外,它们还充当内存屏障。