CC BY 4.0 (除特别声明或转载文章外)
如果这篇博客帮助到你,可以请我喝一杯咖啡~
Project1: 实现一个多线程并发访问的队列
Implement a multi-access threaded queue with multiple threads inserting and multiple threads extracting from the queue. Use mutex-locks to synchronize access to the queue. Document the time for 1000 insertions and 1000 extractions each by 64 insertions threads (Producers) and 64 extraction threads (Consumers). 语言限制:C/C++/Java PS:不能直接使用 STL 或者 JDK 中现有的并发访问队列,请基于普通的 queue 或自行实现
实现思路
在继承 STL 中的适配器queue
的基础上,每次对容器内元素的访问和修改都需要先上锁,结束后解锁。
由于访问操作可以是const
的,因此这个锁需要是mutable
的。
运行结果
所用机器型号为 VAIO Z Flip 2016,基本配置如下:
- Intel(R) Core(TM) i7-6567U CPU @3.30GHZ 3.31GHz
- 8.00GB RAM
编译运行 main.cpp 后,得到如下运行结果:
1
elapsed time: 0.146981s
即进行 64 个生产者和消费者访问之后一共消耗了约 0.146981s。
源代码
wkMultiAccessQueue.hpp
需要开 C++11。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef _wkMultiAccessQueue_hpp_
#define _wkMultiAccessQueue_hpp_
#include <queue>
#include <mutex>
namespace wk
{
template <class T>
class MultiAccessQueue : std::queue<T>
{
private:
mutable std::mutex mu;
public:
void push(T val)
{
std::lock_guard<std::mutex> guard(mu);
std::queue<T>::push(val);
}
void pop()
{
std::lock_guard<std::mutex> guard(mu);
std::queue<T>::pop();
}
T front() const
{
std::lock_guard<std::mutex> guard(mu);
return std::queue<T>::front();
}
};
} // namespace wk
#endif
main.cpp
需要开 C++11。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <chrono>
#include <vector>
#include <thread>
#include <iostream>
#include "wkMultiAccessQueue.hpp"
wk::MultiAccessQueue<int> q;
void producer(int cnt)
{
for (int i = 0; i < cnt; ++i)
q.push(i);
}
void consumer(int cnt)
{
for (int i = 0; i < cnt; ++i)
q.pop();
}
int main()
{
auto begin = std::chrono::system_clock::now();
std::vector<std::thread> vt(64);
for (auto &it : vt)
it = std::thread(producer, 1000);
for (auto &it : vt)
it.join();
for (auto &it : vt)
it = std::thread(consumer, 1000);
for (auto &it : vt)
it.join();
auto end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end - begin;
std::cout << "elapsed time: " << elapsed_seconds.count() << "s\n";
}