目前正在处理一个项目,我目前正在努力处理线程和队列,问题是所有线程都在队列中使用相同的项目。
可复制的例子:
#include <iostream>
#include <queue>
#include <thread>
using namespace std;
void Test(queue<string> queue){
while (!queue.empty()) {
string proxy = queue.front();
cout << proxy << "\n";
queue.pop();
}
}
int main()
{
queue<string> queue;
queue.push("101.132.186.39:9090");
queue.push("95.85.24.83:8118");
queue.push("185.211.193.162:8080");
queue.push("87.106.37.89:8888");
queue.push("159.203.61.169:8080");
std::vector<std::thread> ThreadVector;
for (int i = 0; i <= 10; i++){
ThreadVector.emplace_back([&]() {Test(queue); });
}
for (auto& t : ThreadVector){
t.join();
}
ThreadVector.clear();
return 0;
}
看看这个片段:
void Test(std::queue<std::string> queue) { /* ... */ }
在这里,您将队列对象的副本传递给线程。
该副本对于每个线程都是本地的,因此在每个线程退出后它都会被销毁,因此最终您的程序对queue
驻留在main()
函数中的实际对象没有任何影响。
要解决此问题,您需要使参数采用引用或指针:
void Test(std::queue<std::string>& queue) { /* ... */ }
这使得参数直接引用queue
内部存在的对象,main()
而不是创建副本。
现在,上面的代码仍然不正确,因为queue
它容易发生数据竞争,std::queue
也不std::cout
是线程安全的,并且在当前被另一个线程访问时可能会被另一个线程中断。为了防止这种情况,请使用std::mutex
:
// ...
#include <mutex>
// ...
// The mutex protects the 'queue' object from being subjected to data-race amongst different threads
std::mutex mut;
void Test(std::queue<std::string>& queue) {
std::queue<std::string> tmp;
{
// Swap the actual object with a local temporary object while being protected by the mutex
std::lock_guard<std::mutex> lock(mut);
std::swap(tmp, queue);
}
while (!tmp.empty()) {
std::string proxy = tmp.front();
{
// Call to 'std::cout' needs to be synchronized
std::lock_guard<std::mutex> lock(mut);
std::cout << proxy << "\n";
}
tmp.pop();
}
{
// Now swap back the temporary into the main object
std::lock_guard<std::mutex> lock(mut);
std::swap(queue, tmp);
}
}
这会同步每个线程调用,并在线程queue
仍在访问时阻止来自任何其他线程的访问。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句