Я пишу многопоточную демонстрационную программу с использованием 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 не должен включать несколько элементов.
Я благодарен за любую помощь, которую может предложить каждый!