静态存储器中的STL结构“在线程中丢失”数据

时间:2010-03-02 20:22:51

标签: c++ stl static pthreads shared-memory

我正在使用pthreads编写一个多线程演示程序,其中一个线程将数据加载到STL队列中,另一个线程从中读取。听起来很琐碎,对吗?不幸的是,推入队列的数据正在消失。我不是多线程新手,也不熟悉内存结构 - 然而,这让我很难过。

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

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);

然后启动'producer'线程和'consumer'线程,让他们做自己的事情。生产者线程将新项目推送到队列,然后进入休眠状态。以下是向队列添加内容的行:

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

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

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

2 个答案:

答案 0 :(得分:5)

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

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

你需要extern,这实际上与static相反:

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

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

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

答案 1 :(得分:1)

您应该验证两个线程是否实际访问同一个队列,如果不是,请尝试避免静态队列并在主函数或方便的地方创建它。