lim*_*imp 7 c++ multithreading mutex
我对线程有点新,我试图理解它在C++ 11中是如何工作的.我班上的教授给了我们这个示例代码来演示互斥锁的用法:
#include <list>
#include <mutex>
#include <algorithm>
std::list<int> some_list; // A data structure accessed by multiple threads
std::mutex some_mutex; // This lock will prevent concurrent access to the shared data structure
void
add_to_list(int new_value) {
std::lock_guard<std::mutex> guard(some_mutex); // Since I am going to access the shared data struct, acquire the lock
some_list.push_back(new_value); // Now it is safe to use some_list. RAII automatically releases lock at end of function }
}
bool
list_contains(int value_to_find) {
std::lock_guard<std::mutex> guard(some_mutex); // Must get lock every time I access some_list return
std::find (some_list.begin(),some_list.end(),value_to_find) != some_list.end();
}
Run Code Online (Sandbox Code Playgroud)
我认为代码有些不言自明,但我有一些具体的问题.
互斥锁与列表相关联,但此关联完全是手动的 - 编译器和运行时库不知道这两者是关联的.该关联完全存在于您的文档和头脑中,您有责任确保访问列表的任何线程首先锁定/获取互斥锁.
每当使用互斥锁时,锁定/获取互斥锁的线程将停止(该术语实际上是阻塞),直到没有其他线程拥有该互斥锁.不使用互斥锁的线程不受影响.
您有责任确保只有访问列表的线程锁定/获取互斥锁,并且您还负责确保访问列表的所有线程锁定/获取互斥锁.同样,只有那些线程可以阻止等待互斥锁.
同一个对象有许多不同的名称:"互斥","锁定"或"临界区".守卫使用RAII来锁定/获取互斥锁.
是否不需要专门将互斥体与列表关联起来?
不,您需要手动执行此操作。
如果不是,这是否意味着任何时候使用互斥锁时,所有线程都会停止,直到互斥锁被销毁为止?或者它只是线程的一个子集;也许某个线程池中的线程或以其他方式相互关联?
互斥=互斥。如果两个线程尝试锁定互斥体,其中一个线程将阻塞,直到该互斥体被释放。如果您尝试锁定互斥体,而另一个线程拥有锁,它将阻塞,直到它被释放。
无论哪种情况,仅停止尝试访问数据结构的线程不是更好吗?因为否则,我们并不担心数据竞争等问题。
是的。当存在并发访问问题时,您应该只锁定保护数据结构的互斥体。例如修改数据结构时。这就是为什么您的函数仅在 的持续时间内add_to_list锁定互斥锁 ( ) 。some_mutexsome_list.push_back()
最后,互斥锁和锁有什么区别?互斥锁只是 RAII 锁吗?
C++ lock_guard 是互斥锁的 RAII 包装器。当对象被创建时,互斥体被锁定,当对象被销毁(超出范围)时,互斥体被解锁。