Возможный дубликат:
Есть ли способ отменить/отсоединить будущее в C++11?
Существует функция-член, которая выполняется асинхронно с использованием std::future
и std::async
. В некоторых случаях мне нужно его отменить. (Функция последовательно загружает близлежащие объекты, а иногда объекты выходят за пределы диапазона при загрузке.) Я уже прочитал ответы на этот вопрос касается той же проблемы, но я не могу заставить его работать.
Это упрощенный код с той же структурой, что и моя реальная программа. Вызов Start()
и Kill()
во время работы асинхронного режима вызывает сбой из-за нарушения прав доступа для input
.
На мой взгляд код должен работать следующим образом. Когда вызывается Kill()
, флаг выполнения отключается. Следующая команда get()
должна дождаться завершения потока, что она и делает вскоре, поскольку проверяет флаг выполнения. После отмены потока указатель input
удаляется.
#include <vector>
#include <future>
using namespace std;
class Class
{
future<void> task;
bool running;
int *input;
vector<int> output;
void Function()
{
for(int i = 0; i < *input; ++i)
{
if(!running) return;
output.push_back(i);
}
}
void Start()
{
input = new int(42534);
running = true;
task = async(launch::async, &Class::Function, this);
}
void Kill()
{
running = false;
task.get();
delete input;
}
};
Кажется, что поток не замечает переключения флага выполнения на false. В чем моя ошибка?
std::atomic<bool> running;
? - person aschepler   schedule 13.01.2013input
является указателем на память, выделенную кучей? - person Konrad Rudolph   schedule 13.01.2013running
не синхронизируется. попробуйте объявить его какatomic<bool>
. вы также можете попробовать использоватьvolatile
и синхронизировать вручную, если хотите, скорее всего, два потока работают на разных ядрах, а компилятор хранитrunning
в реестре. - person Andy Prowl   schedule 13.01.2013input
в цикле for:for(int i = 0; i < *input; ++i)
- person Olaf Dietsche   schedule 13.01.2013volatile
тут не поможет, к тредам это не имеет никакого отношения. - person Jonathan Wakely   schedule 13.01.2013volatile
заставляет компилятор не сохранять эту переменную в реестре, чтобы изменения, сделанные потоком, работающим на одном ядре, были видны потокам, работающим на других ядрах. конечно, это не означает, что нет гонки данных, поэтому я указал, что следует использоватьatomic<bool>
- person Andy Prowl   schedule 13.01.2013atomic_bool
илиatomic<bool>
. Я бы вам написал ответ, я приму это. - person danijar   schedule 13.01.2013volatile
только не позволяет компилятору оптимизировать доступ к памяти для переменной, но не мешает ЦП переупорядочивать доступ к памяти, поэтому изменения в памяти, сделанные одним потоком, по-видимому, произошли в другом порядке для другого потока. Это причина существования атомарных и блокировок, которые используют соответствующие барьеры памяти, чтобы гарантировать, что изменения видны другим потокам в правильном порядке. При использовании атомов или блокировокvolatile
не требуется. - person Maxim Egorushkin   schedule 13.01.2013volatile
влияет только на один поток, предотвращая переупорядочение кода компилятором, он ничего не делает для предотвращения аппаратного переупорядочения и ничего не делает для синхронизации памяти между потоками. volatile С++ не похож на volatile Java. См. hpl.hp.com/personal/ Hans_Boehm/c++mm/old_snapshots/ и drdobbs.com/ parallel/volatile-vs-volatile/212701484 и запишите его 100 раз: volatile бесполезно для безопасности потоков - person Jonathan Wakely   schedule 13.01.2013atomic<T>
, а затемvolatile
не дает никаких преимуществ, код уже защищен от гонок и проблем с видимостью. Если не использоватьatomic<T>
(или нестандартные эквиваленты), тоvolatile
недостаточно для корректности, поэтому вам следует использоватьatomic<T>
.volatile
предназначен для доступа к оборудованию, а не для многопоточности. - person Jonathan Wakely   schedule 13.01.2013volatile
в C++ помогает предотвратить гонки данных. в-третьих, я никогда не упоминалvolatile
в Java, что на самом деле является чем-то совершенно другим (кстати, я не программист на Java). я никогда не упоминал, чтоvolatile
заменяет синхронизацию любым возможным способом. - person Andy Prowl   schedule 13.01.2013volatile
само по себе предотвращает гонки данных.volatile
просто заставляет компилятор не сохранять эту переменную в регистре. конечно,atomic<bool>
— это первый вариант, поэтому я написал его первым, кстати - person Andy Prowl   schedule 13.01.2013volatile
каким-либо образом относится к многопоточности. - person Jonathan Wakely   schedule 13.01.2013volatile
не имеет отношения к многопоточности, которая является темой этого вопроса. например, прочитайте это: drdobbs.com/cpp/volatile- многопоточные программисты-b/. конечно,atomic<bool>
действительно решает всю проблему, но упоминание о похожих темах не кажется мне преступлением - person Andy Prowl   schedule 13.01.2013volatile
как тег именно потому, что в противном случае он бесполезен и, следовательно, не используется; но это всего лишь тег, если бы он мог использовать вместо этого тегhelloworld
, он мог бы это сделать. - person Matthieu M.   schedule 13.01.2013volatile
недостаточно для предотвращения гонки данных (для этого вам нужны мьютексы), но также указано, что это должно быть сделано ( Если инкремент и декремент должны вызываться из разных потоков, приведенный выше фрагмент содержит ошибку. Во-первых, ctr_ должен быть изменчивым). Теперь, если Александреску ошибается, как говорит Джонатан Уэйкли, то мне очень жаль, я всегда находил его надежным источником. Я знаю, что C++11 имеет лучший примитив. Я не согласен,volatile
не имеет отношения. Останавливаться. - person Andy Prowl   schedule 13.01.2013const == thread safe
см. channel9.msdn.com/posts/ - person Maxim Egorushkin   schedule 13.01.2013