在项目中,我达到了一个要求线程上的线程之间进行通信的地步,而且很可能要写入,所以同步是必须的。但是,除了基本级别之外,我真的不了解同步。
请考虑此链接中的最后一个示例:http://www.bogotobogo.com/cplusplus/C11/7_C11_Thread_Sharing_Memory.php
#include <iostream>
#include <thread>
#include <list>
#include <algorithm>
#include <mutex>
using namespace std;
// a global variable
std::list<int>myList;
// a global instance of std::mutex to protect global variable
std::mutex myMutex;
void addToList(int max, int interval)
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
void printList()
{
// the access to this function is mutually exclusive
std::lock_guard<std::mutex> guard(myMutex);
for (auto itr = myList.begin(), end_itr = myList.end(); itr != end_itr; ++itr ) {
cout << *itr << ",";
}
}
int main()
{
int max = 100;
std::thread t1(addToList, max, 1);
std::thread t2(addToList, max, 10);
std::thread t3(printList);
t1.join();
t2.join();
t3.join();
return 0;
}
该示例演示了三个线程(两个编写者和一个读者)如何访问一个公共(public)资源(列表)。
使用了两个全局函数:一个由两个编写器线程使用,一个由读取器线程使用。这两个函数都使用lock_guard锁定相同的资源,即列表。
现在,这就是我无法解决的问题:读取器在与两个写入器线程不同的范围内使用锁,但仍锁定相同的资源。这怎么工作?我对互斥量的有限理解非常适合于writer函数,在那里您使用完全相同的函数获得了两个线程。我可以理解,在您即将进入保护区时会立即进行检查,如果已经有人在里面,则请稍候。
但是,当范围不同时?这将表明存在某种机制,其功能比进程本身更强大,某种运行时环境会阻止“后期”线程的执行。但是我认为c++中没有这样的东西。所以我很茫然。
这到底是怎么回事?
最佳答案
myMutex
是全局的,用于保护myList
。 guard(myMutex)
只是接合了锁,而从块的退出导致了销毁,从而解除了锁的接合。 guard
只是启用和解除锁定的一种便捷方式。
这样一来,mutex
不会保护任何数据。它只是为提供了一种保护数据的方式。是保护数据的设计模式。因此,如果我编写自己的函数来修改列表,如下所示,则mutex
无法保护它。
void addToListUnsafe(int max, int interval)
{
for (int i = 0; i < max; i++) {
if( (i % interval) == 0) myList.push_back(i);
}
}
只有在需要访问数据的所有代码段都在访问之前脱离并在其完成后脱离啮合的情况下,该锁才起作用。这种在每次访问之前和之后接合和分离锁的设计模式可以保护数据(在您的情况下为
myList
)现在您会怀疑,为什么要完全使用
mutex
,为什么不使用bool
呢?是的,可以,但是您必须确保bool
变量具有某些特征,包括但不限于以下列表。有多种
synchronization
机制提供“更好的锁定”(跨进程与跨线程,多处理器与单处理器等),但代价是“性能较慢”,因此您应该始终选择一种足以满足要求的锁定机制你的情况。关于c++ - std::lock_guard示例,解释其工作原理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/35252119/