[英]C++11 thread to modify std::list
我將發布我的代碼,然后告訴您我在做什么。
#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();
}
我認為這段代碼正在做的是在列表末尾添加10000個元素。 對於我們添加的每10個,啟動一個(單個)線程,該線程將刪除列表的前10個元素(在啟動線程時)。
我不希望這會刪除每個列表元素,我只是想看看在從開頭刪除元素的同時是否可以添加到列表的末尾。 在Visual Studio中,我經常會遇到“ list iterators incompatible
”錯誤,但我認為問題出在跨平台上。
我的想法怎么了? 我知道是這樣
編輯:
因此,我現在看到此代碼非常不正確。 真的,我只希望一次激活一個輔助線程來刪除元素,這就是為什么我盡管調用“擦除”是可以的。 但是,我不知道如何在不加入線程的情況下聲明線程,如果我等待它,那么我真的看不到這樣做的意義。
我應該在循環之前聲明我的線程,讓它等待主線程發出的信號嗎?
為了明確起見,我的目標是執行以下操作:我想抓住一個線程上的鍵盤按鍵並將它們存儲在列表中,並且每隔一段時間將它們記錄到另一個線程上的文件中,同時刪除我記錄的內容。 由於我不想花很多時間寫磁盤,因此我想寫離散塊(共10個)。
感謝克里斯托夫和其他所有人。 現在是我的代碼...我可能沒有正確使用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;
}
您的代碼不適用於:
這里有一些改進(請看注釋行):
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
}
...
順便說一句,我建議您看一下lock_guard<mutex>
中的鎖,因為這些鎖可以確保在所有情況下都可以解鎖(尤其是在出現此類異常或意外驚喜時)。
編輯:通過使它成為atomic<bool>
,我避免了使用互斥鎖running
的鎖定保護。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.