std::mutex 阻止线程修改什么?

What does std::mutex prevent threads from modifying?

.lock().try_lock() 时,内存的哪一部分被 mutex 锁定,是只是函数还是整个程序都被锁定?

除了互斥量之外,没有任何东西被锁定。其他一切继续运行ning(直到它试图锁定一个已经锁定的互斥体)。互斥锁只是为了让两个线程不能同时运行互斥锁和互斥解锁之间的代码。

互斥量并不会真正锁定任何东西,除了它自己。您可以将互斥量视为一扇门,您只能从内部解锁它。当门被锁定时,任何试图锁定互斥锁的线程都将坐在门那里,等待门后面的当前线程解锁它并让他们进入。当他们的门没有被锁定时,然后当你调用 lock 你可以进去,关闭并锁上门,现在没有线程可以通过门,直到你解锁并让它们进入。

m.lock() 并没有真正锁定 任何东西。 它所做的是 等待 所有权 互斥。一个互斥锁要么被恰好一个线程拥有,要么可用m.lock() 等到互斥锁可用,然后它以调用线程的名义获得它的所有权。

m.unlock 释放互斥量(即放弃所有权),导致互斥量再次可用。


互斥体还执行另一个非常重要的功能。在现代 C++ 中,当某个线程 T 对不同的内存位置执行一系列不同值的赋值时,系统不保证其他线程 U、V 和 W 何时会看到这些赋值,其他线程是否会看到赋值发生按照线程 T 执行它们的相同顺序,甚至其他线程是否会曾经看到分配。

有一些相当复杂的规则来管理程序员可以执行的操作以确保不同的线程看到共享内存对象的一致视图 (Google "C++ memory model"),但这里有一个简单的规则:

线程 T 在释放某个互斥量 M 之前所做的任何事情都保证对任何其他线程 U 可见 线程 U 随后锁定相同的互斥量 M。

互斥体不会锁定任何东西。您只需 使用 互斥锁来与代码的其他部分进行通信,他们应该考虑 决定需要保护其免受多个线程访问的任何内容同时暂时禁止入内。

您可以将互斥体视为类似布尔值的东西 okToModify。每当您想编辑某些内容时,您都会检查 okToModify 是否为 true。如果是,则将其设置为 false(防止任何其他线程修改它),更改它,然后将 okToModify 设置回 true 以告诉其他线程您已完成并给他们修改的机会:

// WARNING! This code doesn't actually work as a lock!
//    it is just an example of the concept.
struct LockedInt {
    bool okToModify; // This would be your mutex instead of a bool.
    int integer;
};

struct LockedInt myLockedInt = { true, 0 };    

...

while (myLockedInt.okToModify == false)
    ; // wait doing nothing until whoever is modifying the int is done.
myLockedInt.okToModify = false; // Prevent other threads from getting out of while loop above.
myLockedInt.integer += 1;
myLockedInt.okToModify = true; // Now other threads get out of the while loop if they were waiting and can modify.

上面的 while 循环和 okToModify = false 基本上是锁定互斥量的作用,okToModify = true 是解锁互斥量的作用。

现在,为什么我们需要互斥量而不使用布尔值?因为线程可能与上面那三行同时 运行 。锁定互斥量的代码实际上保证了等待 okToModify 变为 true 和设置 okToModify = false 是一次性发生的,因此没有其他线程可以得到 "in between the lines",因为例如,使用称为 "compare-and-exchange".

的特殊机器代码指令

所以使用布尔值而不是互斥量,但是你可以想到一个互斥锁作为一种特殊的、线程安全的布尔值。