使用互斥锁锁定向量 - Boost
Posted
技术标签:
【中文标题】使用互斥锁锁定向量 - Boost【英文标题】:Lock a vector with a mutex - Boost 【发布时间】:2013-10-22 09:25:32 【问题描述】:我正在为路由器编写代码,并且我想在接收器线程上接收到数据包后,将该数据包(目前为“unsigned char *”类型)存储在向量中。我有两个接收器线程链接到两个不同的接口,并且接收器线程应该仅在另一个线程尚未访问向量时存储接收到的数据包。
除了两个接收线程之外,我将有一个处理数据包的主线程和两个发送线程,一个用于每个接口。总线程数为 5。为了防止不同线程在从向量中写入或读取时出现问题,我听说了一个互斥锁,它应该为其他(在这种情况下)线程锁定向量,直到有问题的线程之后从向量中读取或写入完成。
我想知道的是这是如何处理成代码的。一些例子将不胜感激。我对 C++、Boost 和 Raw Sockets 都很陌生。最重要的是,我还不太喜欢在 C++ 中使用不同的类。我非常了解它们在 Java 和 C# 中的工作方式,但我发现 C++ 非常不同(因为头文件)。我将所有代码都放在一个巨大的主类中,这可能不是很好的编码风格,但目前就是这样。
我应该创建一个类(.h 和 .cpp 文件)来处理这个向量,还是应该在我的巨型主类中实现它,如果是这样,我会很高兴有一些简单的例子。下面是我希望我的程序如何工作的示例。我已经有了 RecvThread,并且可以打印出数据包的 MAC Hdr。
void RecvThread()
//receive a packet
while(true)
//get lock status from vector
if(vector is locked)
usleep(10000);
else
//lock vector
//save packet in vector
//unlock vector
void SendThread()
while(true)
//get lock status from vector
if(vector is locked)
usleep(10000);
else
//lock vector
//get packet from vector
//unlock vector
//send the packet
void MainThread()
while(true)
if(recv vector is empty)
usleep(10000);
else if(recv vector is locked)
usleep(10000);
else
//lock recv vector
//get packet in front of queue
//unlock recv vector
//process packet (update different fields)
//get packet interface (either 1 or 2)
if(send vector (matching interface) is locked)
usleep(10000);
else
//lock send vector (matching interface)
//save packet to send vector (matching interface)
//unlock send vector (matching interface)
int main()
//create Recv vector
//create Send vector 1 and 2 (one for each interface)
//create and join RecvThread 1 and 2
//create and join SendThread 1 and 2
//create and join MainThread
【问题讨论】:
您可以在没有类的情况下使用 .h 文件和 .cpp。如果您在其中一个中写单词 class,您就有一个类。 在您的情况下,您将在您编写 //lock 向量 cmets 的位置锁定一个互斥锁。不过,您不需要获取锁定状态,boost 库会为您处理此问题 【参考方案1】:希望这能给你一些想法。没有测试它,因为它显然不完整:)
关键是boost::lock_guard<boost::mutex> lock(mx_);
,因为这一行一次只能由一个线程执行。实际发生的情况是线程 A 例如调用此函数,因为它是第一个到达那里的线程boost::lock_guard<boost::mutex> lock(mx_);
立即返回,线程可以继续进入所谓的临界区(锁定后的代码段)。基本上boost::lock_guard<boost::mutex> lock(mx_);
仅在临界区内没有其他线程时才返回。如果临界区已经被另一个线程访问,boost::lock_guard<boost::mutex> lock(mx_);
在另一个线程离开临界区之前不会返回。为了让等待线程现在继续进行,需要解锁互斥锁。在 boost 中,一旦阻塞线程(第一个进入该部分)离开具有临界区的函数范围,就会自动完成此操作。离开作用域会破坏变量mx_
,它允许创建和锁定另一个同名的互斥锁。
编辑:您不会专门锁定一个变量,例如向量。您锁定一段代码,访问该变量的位置。
class Receiver
private:
boost::mutex mx_;
int *data_; // I need protection
public:
bool receive_data()
// Prepare connection and do some stuff...
void some_function()
// Before we access data_, we need to make sure only the current thread does so.
// Mutex will unlock once the scope of this function is left
boost::lock_guard<boost::mutex> lock(mx_);
// Access data_ here (mutex is locked)
//....
// End of scope and mutex unlocks automatically since it's destroyed
return true; // Will unlock the mutex since the function's scope is left.
;
【讨论】:
它明确地让我知道它应该如何工作,但这仅在课堂上可行吗?现在我的 RecvThread 函数只是从原始接口接收一个数据包而不是运行一个类......我主要关心的是我应该如何编写创建可锁定向量的特定部分...... 不不抱歉,当然你可以在任何地方锁定它。只需在函数内部执行此操作,以便在函数返回后自动解锁。 所以我可以编写一个函数:void LockVector(vectorconst
引用传递向量。重要的部分是建立lock_guard
before 尝试push_back
字符。试图向向量中添加东西,以及这些修改所带来的所有影响,都是这里的关键问题。另外,请不要说“锁定矢量”。正如 potAito 已经说过的,您不会锁定孤立的对象,但通常会阻止控制流通过同步点,例如mutex
.
@potAito 那个长长的答案是彩虹尽头的“金罐”! :D 非常感谢!拥有 AddToVector 和 RemoveFromVector 函数是否有意义?因为他们都可以调用保护函数,所以这两者会发生冲突吗?最后一个小问题:将 mx_ 和 vector 变量实例化为全局变量是否是个好主意?那是在 main.cpp 文件的任何函数之前的顶部..以上是关于使用互斥锁锁定向量 - Boost的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Python 进程中访问由 C++ 进程创建的互斥锁?
在已锁定的互斥体上使用 boost::interprocess 条件变量