c++ - 静态内存中的STL结构 'Losing' 跨线程数据

标签 c++ stl static pthreads shared-memory

我正在使用 pthreads 编写一个多线程演示程序,其中一个线程将数据加载到 STL 队列中,另一个线程从中读取数据。听起来微不足道,对吧?不幸的是,插入队列的数据正在消失。我对多线程并不陌生,也不熟悉内存结构 - 然而,这让我感到难过。

这些是我对队列本身和保护它的互斥锁的声明,它们位于客户端代码包含的 header 中:

static std::queue<int32_t> messageQueue;
static pthread_mutex_t messageQueueLock; 

当程序启动时,它用进程共享属性初始化互斥量:

pthread_mutexattr_t sharedAttr;
pthread_mutexattr_init(&sharedAttr);
pthread_mutexattr_setpshared(&sharedAttr, PTHREAD_PROCESS_SHARED);
pthread_mutex_init(&messageQueueLock, &sharedAttr);

然后它启动“生产者”线程和“消费者”线程,让它们做自己的事情。生产者线程将一个新项目推送到队列中,然后进入休眠状态。以下是它向队列添加内容的行:

pthread_mutex_lock(&messageQueueLock);
messageQueue.push(message);
pthread_mutex_unlock(&messageQueueLock);

然后它休眠并让消费者线程接管。然而,当消费者线程检查队列中的项目时,队列神奇地空了。

我已经使用 gdb 逐步完成了程序。下面是我运行的输出。您可以看到生产者在哪里向队列中添加了一些东西,我打印了队列的大小以确保它在那里,有一个到消费者线程的上下文切换,我再次打印了队列的大小,它是空的。检查一下:

(gdb) b main_ex.cpp:70
Breakpoint 1 at 0x100006a24: file main_ex.cpp, line 70.
(gdb) run
Starting program: a.out 
Reading symbols for shared libraries ++. done
Creating the mutex.
Producer thread starting up. 
PRODUCER: Creating a message to send.
PRODUCER: Adding the message to the queue.
[Switching to process 7432]

Breakpoint 1, yourProcess () at main_ex.cpp:70
70      pthread_mutex_lock(&messageQueueLock);
(gdb) n
71      messageQueue.push(message);
(gdb) p messageQueue.size()
$1 = 0
(gdb) n
72      pthread_mutex_unlock(&messageQueueLock);
(gdb) p messageQueue.size()
$2 = 1
(gdb) b consumer.cpp:81
Breakpoint 2 at 0x1000043f7: file consumer.cpp, line 81.
(gdb) c
Continuing.
PRODUCER: Sleep time!
[Switching to process 7432]

Breakpoint 2, Producer::processMessageQueue (this=0x1001000c0) at producer.cpp:81
81      pthread_mutex_lock(&messageQueueLock);
(gdb) n
83      if(messageQueue.empty()) {
(gdb) p messageQueue.size()
$3 = 0
(gdb) quit

所以,我真的不确定发生了什么。队列仅在关键部分(读/写)中被访问,队列是静态的,并且 header 是 if-def'd 不被多重包含。

我很感激任何人可以提供的任何帮助!

最佳答案

header 保护防止每个翻译单元被多重包含。但是,不同的翻译单元将重新包含它们。

在您的情况下,他们似乎每个人都有自己的静态队列和互斥量。另外,即使您是正确的,也要考虑:如果不重新包含 header ,翻译单元将不知道队列和互斥体是什么!您会尝试使用一些未声明的标识符。

需要extern,其实和static相反:

extern std::queue<int32_t> messageQueue;
extern pthread_mutex_t messageQueueLock;

然后在一个单元中,实际定义它们:

std::queue<int32_t> messageQueue;
pthread_mutex_t messageQueueLock;

关于c++ - 静态内存中的STL结构 'Losing' 跨线程数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2366461/

相关文章:

c++静态函数未找到

java - 为泛型类的每个类型参数创建单独的单例的最佳习惯用法?

c# - 想在 asp.net 中使用 c++ 库和 dll

c++ - 对 std::unordered_map 中使用的 std::array 进行哈希处理

c++ - 如何在 Boost::Spirit::Lex 中使用指针作为标记属性?

c++ - Visual Studio 2019 : Pass include paths between chain-referenced projects

c++ - STL 堆栈和 priority_queue 的插入器

c++ - 将 vector 写入文件并读回

c++ - UTF8 到/从 STL 中的宽字符转换

c++ - C++ 类的静态变量初始化,为什么要包含数据类型?