【发布时间】:2021-06-01 06:19:14
【问题描述】:
我用链表实现了一个队列,我希望多个线程以正确的顺序推送元素。我使用互斥锁锁定了我的成员函数,但终端打印的数字仍然不正确,应该是 1、2、3、4、5、6。而是打印错误的顺序,例如 3,1,4,2,5,6。这意味着互斥锁 DIDNT 起作用。有人可以告诉我为什么吗?以及如何解决这个问题?
// Implement a queue<int>,need functions: push_front, back, pop_back, and print
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
struct ListNode {
ListNode* next;
int val;
ListNode(int x) {
val = x;
this->next = nullptr;
}
};
class Queue {
public:
Queue() {
head = new ListNode(0); // dummy head
tail = head;
}
void push_front(int x) { // add node at then end of linked list
lock_guard<mutex> lock(m);
tail->next = new ListNode(x);
tail = tail->next;
}
int pop_back() { // remove the first node of the linked list
lock_guard<mutex> lock(m);
ListNode* back = head->next;
if (back == nullptr) {
throw invalid_argument("empty queue");
}
head->next = back->next;
back->next = nullptr;
return back->val;
}
void print() {
lock_guard<mutex> lock(m);
ListNode* p = head->next;
while (p != nullptr) {
cout << p->val << endl;
p = p->next;
}
}
private:
mutable mutex m;
// Implement with linked list
ListNode* head;
ListNode* tail;
};
int main() {
Queue* queue = new Queue();
// Multiple threads push at the same time --> order is wrong
thread t1 = thread(&Queue::push_front, queue, 1);
thread t2 = thread(&Queue::push_front, queue, 2);
thread t3 = thread(&Queue::push_front, queue, 3);
thread t4 = thread(&Queue::push_front, queue, 4);
thread t5 = thread(&Queue::push_front, queue, 5);
thread t6 = thread(&Queue::push_front, queue, 6);
t1.join();
t2.join();
t3.join();
t4.join();
t5.join();
t6.join();
queue->print();
}
【问题讨论】:
-
Mutex 不保证订单。它只会确保不会同时添加到队列中(与共享变量同时发生并可能损坏共享变量)。
-
t1到t6的哪一个线程被安排在第一个取决于机会。没有必要检查其他任何东西。 -
无关:不需要动态分配
queue。考虑将Queue* queue = new Queue();替换为Queue queue;,将thread(&Queue::push_front, queue, 1);(和朋友)替换为thread(&Queue::push_front, &queue, 1);以提供队列的地址,并将queue->print();替换为queue.print();。一般来说,Why should C++ programmers minimize use of 'new'? -
请注意,如果您希望 push_front() 操作以严格的顺序执行,则无需生成任何线程;相反,您可以直接从主线程调用 push_front() 。能够异步地做事(因此没有任何固定的顺序)是使用线程的主要原因。
标签: c++ multithreading class c++11 mutex