帮助我确定理解互斥量的一些问题
Some questions to help me to be sure to understand mutex
大家好,
我对互斥量有一些疑问(主题已经很具体)。所以,我需要确保没有误解(https://en.cppreference.com/w/cpp/thread/mutex):
1) 我想确保 std::mutex 不能同时在 2 个线程之间共享。是真的吗?
2) 如果随机地,两个独立的线程同时请求互斥锁,会发生什么情况?
3) 根据我的理解,当一个线程获取互斥锁时,它会阻止任何其他线程同时修改全局变量。好理解吗?
如果对于这些问题中的任何一个,我不正确,你能纠正吗?
谢谢你
1) 应该 共享。否则你将如何使用它???
编辑:好的,这个问题似乎有点误导。在这种情况下,"shared" 是什么意思?
Edit2:如果 "shared" 你的意思是一个互斥量可以被多个线程持有,那么答案是:这不可能发生。
2) 即使它在两个不同的内核上恰好在同一物理时间发生,也会有一些仲裁机制将互斥量提供给一个或另一个线程。
3) 不。当 other 线程获取互斥量时,您 知道 您不能修改受此互斥量保护的变量而不会产生任何后果,并且应该编写不存在此类修改的代码。但是互斥量本身绝不会 阻止 这样的修改。当然,你不应该在不持有互斥量的情况下读取这些变量。
1) 它们可以共享,但互斥锁用于防止线程同时访问您希望一次只能由一个线程访问和修改的资源。
2)互斥量的语义是两个线程不能同时锁定同一个互斥量
3) 互斥量阻止任何其他线程同时修改互斥量锁定后处理的资源,直到您解锁互斥量。全局变量就是其中之一。
您可能应该进一步阅读有关互斥量(mutexes?mutices?)的内容,因为它不仅是 c++ 的概念,而且是一般计算机科学的概念。回答您的问题:
- 是的,没错,这就是互斥锁的全部意义所在。在任何时间点,只有一个线程可以拥有互斥锁。
- 其中一个线程将获得互斥锁,另一个则不会。实现将处理这一点,即使访问是在同一物理时间在多个物理内核上发生的。
- 不完全是,您始终可以选择忽略互斥锁并仍然更改这些变量。如何解决并发问题取决于你。
编辑
我认为某些语言提供了包装变量的容器,使得它们一次只能由一个线程读取。我认为它们在 Java.
中被称为监视器
一般概念:
std::mutex m;
int globalVar;
void foo()
{
//Acquire lock or wait, if another thread already acquired the lock.
mutex.lock();
//At any given time this code will be executed by one thread only (or none)
globalVar = bar();
mutex.unlock();
}
//However you can choose to ignore the mutex...
void evilFoo()
{
//This can be executed by multiple threads at the same time (even parallel to foo())
globalVar = bar();
}
假设爱丽丝给了鲍勃 5 件东西。您将拥有类似的代码。
alice -= 5;
bob +=5;
我们不希望出现这样的情况,即我们从 Alice 那里拿走了 5,但还没有把 5 给 Bob。
std::thread
使用操作系统对 pre-emptive 多线程的支持。这意味着操作可以在任何时间点中断一个线程并安排另一个线程。在 multi-core 台机器上,它们甚至可以同时 运行。这意味着线程可能会看到不一致的数据。
Mutex 是一个操作系统对象,其工作是确保一次只有一个线程可以访问代码的关键部分。
因此,当线程 1 进入互斥量时,它会增加互斥量的访问计数。当下一个线程试图进入互斥锁时,它检测到访问计数不为零。然后操作系统挂起线程。
当第一个线程释放互斥量时,其他线程将再次变为 运行nable。这意味着操作系统可能会根据其优先级将它们安排到 运行 现在或稍后。
然后,新的 运行 可用线程可能会尝试使用与上述相同的规则进入互斥体。
这意味着如果使用了公共互斥锁,则任何两个线程都不能同时进入受互斥锁保护的代码。
大家好, 我对互斥量有一些疑问(主题已经很具体)。所以,我需要确保没有误解(https://en.cppreference.com/w/cpp/thread/mutex):
1) 我想确保 std::mutex 不能同时在 2 个线程之间共享。是真的吗?
2) 如果随机地,两个独立的线程同时请求互斥锁,会发生什么情况?
3) 根据我的理解,当一个线程获取互斥锁时,它会阻止任何其他线程同时修改全局变量。好理解吗?
如果对于这些问题中的任何一个,我不正确,你能纠正吗?
谢谢你
1) 应该 共享。否则你将如何使用它???
编辑:好的,这个问题似乎有点误导。在这种情况下,"shared" 是什么意思?
Edit2:如果 "shared" 你的意思是一个互斥量可以被多个线程持有,那么答案是:这不可能发生。
2) 即使它在两个不同的内核上恰好在同一物理时间发生,也会有一些仲裁机制将互斥量提供给一个或另一个线程。
3) 不。当 other 线程获取互斥量时,您 知道 您不能修改受此互斥量保护的变量而不会产生任何后果,并且应该编写不存在此类修改的代码。但是互斥量本身绝不会 阻止 这样的修改。当然,你不应该在不持有互斥量的情况下读取这些变量。
1) 它们可以共享,但互斥锁用于防止线程同时访问您希望一次只能由一个线程访问和修改的资源。
2)互斥量的语义是两个线程不能同时锁定同一个互斥量
3) 互斥量阻止任何其他线程同时修改互斥量锁定后处理的资源,直到您解锁互斥量。全局变量就是其中之一。
您可能应该进一步阅读有关互斥量(mutexes?mutices?)的内容,因为它不仅是 c++ 的概念,而且是一般计算机科学的概念。回答您的问题:
- 是的,没错,这就是互斥锁的全部意义所在。在任何时间点,只有一个线程可以拥有互斥锁。
- 其中一个线程将获得互斥锁,另一个则不会。实现将处理这一点,即使访问是在同一物理时间在多个物理内核上发生的。
- 不完全是,您始终可以选择忽略互斥锁并仍然更改这些变量。如何解决并发问题取决于你。
编辑
我认为某些语言提供了包装变量的容器,使得它们一次只能由一个线程读取。我认为它们在 Java.
中被称为监视器一般概念:
std::mutex m;
int globalVar;
void foo()
{
//Acquire lock or wait, if another thread already acquired the lock.
mutex.lock();
//At any given time this code will be executed by one thread only (or none)
globalVar = bar();
mutex.unlock();
}
//However you can choose to ignore the mutex...
void evilFoo()
{
//This can be executed by multiple threads at the same time (even parallel to foo())
globalVar = bar();
}
假设爱丽丝给了鲍勃 5 件东西。您将拥有类似的代码。
alice -= 5;
bob +=5;
我们不希望出现这样的情况,即我们从 Alice 那里拿走了 5,但还没有把 5 给 Bob。
std::thread
使用操作系统对 pre-emptive 多线程的支持。这意味着操作可以在任何时间点中断一个线程并安排另一个线程。在 multi-core 台机器上,它们甚至可以同时 运行。这意味着线程可能会看到不一致的数据。
Mutex 是一个操作系统对象,其工作是确保一次只有一个线程可以访问代码的关键部分。
因此,当线程 1 进入互斥量时,它会增加互斥量的访问计数。当下一个线程试图进入互斥锁时,它检测到访问计数不为零。然后操作系统挂起线程。
当第一个线程释放互斥量时,其他线程将再次变为 运行nable。这意味着操作系统可能会根据其优先级将它们安排到 运行 现在或稍后。
然后,新的 运行 可用线程可能会尝试使用与上述相同的规则进入互斥体。
这意味着如果使用了公共互斥锁,则任何两个线程都不能同时进入受互斥锁保护的代码。