0

我正在使用 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);

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

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 以不被多重包含。

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

4

2 回答 2

5

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

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

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

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

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

std::queue<int32_t> messageQueue;
pthread_mutex_t messageQueueLock;
于 2010-03-02T20:33:14.587 回答
1

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

于 2010-03-02T20:35:55.427 回答