[英]C++11 thread to modify std::list
I'll post my code, and then tell you what I think it's doing. 我将发布我的代码,然后告诉您我在做什么。
#include <thread>
#include <mutex>
#include <list>
#include <iostream>
using namespace std;
...
//List of threads and ints
list<thread> threads;
list<int> intList;
//Whether or not a thread is running
bool running(false);
//Counters
int busy(0), counter(0);
//Add 10000 elements to the list
for (int i = 0; i < 10000; ++i){
//push back an int
intList.push_back(i);
counter++;
//If the thread is running, make a note of it and continue
if (running){
busy++;
continue;
}
//If we haven't yet added 10 elements before a reset, continue
if (counter < 10)
continue;
//If we've added more than 10 ints, and there's no active thread,
//reset the counter and launch
counter = 0;
threads.push_back(std::thread([&]
//These iterators are function args
(list<int>::iterator begin, list<int>::iterator end){
//mutex for the running bool
mutex m;
m.lock();
running = true;
m.unlock();
//Remove either 10 elements or every element till the end
int removed(0);
while (removed < 10 && begin != end){
begin = intList.erase(begin);
removed++;
}
//unlock the running bool
m.lock();
running = false;
m.unlock();
//Pass into the thread func the current beginning and end of the list
}, intList.begin(), intList.end()));
}
for (auto& thread : threads){
thread.join();
}
What I think this code is doing is adding 10000 elements to the end of a list. 我认为这段代码正在做的是在列表末尾添加10000个元素。 For every 10 we add, launch a (single) thread that deletes the first 10 elements of the list (at the time the thread was launched).
对于我们添加的每10个,启动一个(单个)线程,该线程将删除列表的前10个元素(在启动线程时)。
I don't expect this to remove every list element, I was just interested in seeing if I could add to the end of a list while removing elements from the beginning. 我不希望这会删除每个列表元素,我只是想看看在从开头删除元素的同时是否可以添加到列表的末尾。 In Visual Studio I get a "
list iterators incompatible
" error quite often, but I figure the problem is cross platform. 在Visual Studio中,我经常会遇到“
list iterators incompatible
”错误,但我认为问题出在跨平台上。
What's wrong with my thinking? 我的想法怎么了? I know it's something
我知道是这样
EDIT: 编辑:
So I see now that this code is very incorrect. 因此,我现在看到此代码非常不正确。 Really I just want one auxiliary thread active at a time to delete elements, which is why I though calling erase was ok.
真的,我只希望一次激活一个辅助线程来删除元素,这就是为什么我尽管调用“擦除”是可以的。 However I don't know how to declare a thread without joining it up, and if I wait for that then I don't really see the point of doing any of this.
但是,我不知道如何在不加入线程的情况下声明线程,如果我等待它,那么我真的看不到这样做的意义。
Should I declare my thread before the loop and have it wait for a signal from the main thread? 我应该在循环之前声明我的线程,让它等待主线程发出的信号吗?
To clarify, my goal here is to do the following: I want to grab keyboard presses on one thread and store them in a list, and every so often log them to a file on a separate thread while removing the things I've logged. 为了明确起见,我的目标是执行以下操作:我想抓住一个线程上的键盘按键并将它们存储在列表中,并且每隔一段时间将它们记录到另一个线程上的文件中,同时删除我记录的内容。 Since I don't want to spend a lot of time writing to the disk, I'd like to write in discrete chunks (of 10).
由于我不想花很多时间写磁盘,因此我想写离散块(共10个)。
Thanks to Christophe, and everyone else. 感谢克里斯托夫和其他所有人。 Here's my code now... I may be using lock_guard incorrectly.
现在是我的代码...我可能没有正确使用lock_guard。
#include <thread>
#include <mutex>
#include <list>
#include <iostream>
#include <atomic>
using namespace std;
...
atomic<bool> running(false);
list<int> intList;
int busy(0), counter(0);
mutex m;
thread * t(nullptr);
for (int i = 0; i < 100000; ++i){
//Would a lock_guard here be inappropriate?
m.lock();
intList.push_back(i);
m.unlock();
counter++;
if (running){
busy++;
continue;
}
if (counter < 10)
continue;
counter = 0;
if (t){
t->join();
delete t;
}
t = new thread([&](){
running = true;
int removed(0);
while (removed < 10){
lock_guard<mutex> lock(m);
if (intList.size())
intList.erase(intList.begin());
removed++;
}
running = false;
});
}
if (t){
t->join();
delete t;
}
Your code won't work for because: 您的代码不适用于:
Here some improvements (look at the commented lines): 这里有一些改进(请看注释行):
atomic<bool> running(false); // <=== atomic (to avoid unnecessary use of mutex)
int busy(0), counter(0);
mutex l; // define the mutex here, so that it will be the same for all threads
for (int i = 0; i < 10000; ++i){
l.lock(); // <===you need to protect each access to the list
intList.push_back(i);
l.unlock(); // <===and unlock
counter++;
if (running){
busy++;
continue;
}
if (counter < 10)
continue;
counter = 0;
threads.push_back(std::thread([&]
(){ //<====No iterator args as they might be outdated during executionof threads!!
running = true; // <=== no longer surrounded from lock/unlock as it is now atomic
int removed(0);
while (removed < 10){
l.lock(); // <====you really need to protect access to the list
if (intList.size()) // <=== check if elements exist NOW
intList.erase(intList.begin()); // <===use current data, not a prehistoric outdated local begin !!
l.unlock(); // <====end of protected section
removed++;
}
running = false; // <=== no longer surrounded from lock/unlock as it is now atomic
})); //<===No other arguments
}
...
By the way, I'd suggest that you have a look at lock_guard<mutex>
for the locks, as these ensure the unlock in all circumstances (especially when there are exceptions or orhter surprises like this). 顺便说一句,我建议您看一下
lock_guard<mutex>
中的锁,因为这些锁可以确保在所有情况下都可以解锁(尤其是在出现此类异常或意外惊喜时)。
Edit: I've avoided the lock protection of running
with a mutex, by making it atomic<bool>
. 编辑:通过使它成为
atomic<bool>
,我避免了使用互斥锁running
的锁定保护。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.