Вопрос о Потоке C++ - устанавливание значения для указания на поток закончилось

HandyJSON - еще один вариант для работы с JSON для вас. https://github.com/alibaba/handyjson

Он отделяет JSON от объекта напрямую. Нет необходимости указывать отношение отображения, нет необходимости наследовать из NSObject. Просто определите свой чистый-быстрый класс / struct и десериальный JSON.

class Animal: HandyJSON {
    var name: String?
    var id: String?
    var num: Int?

    required init() {}
}

let jsonString = "{\"name\":\"cat\",\"id\":\"12345\",\"num\":180}"

if let animal = JSONDeserializer.deserializeFrom(jsonString) {
    print(animal)
}

10
задан Piotr Dobrogost 11 July 2009 в 19:18
поделиться

5 ответов

Вы никогда не упоминали тип finished_flag...

Если это - прямой bool, то это могло бы работать, но это - конечно, плохая практика по нескольким причинам. Во-первых, некоторые компиляторы будут кэшировать чтения finished_flag переменной, так как компилятор не всегда берет то, что это пишется в другим потоком. Можно обойти это путем объявления bool энергозависимого, но это берет нас в неправильном направлении. Даже если бы чтения и записи происходят, как Вы ожидали бы, нет ничего, чтобы мешать планировщику ОС чередовать два потока половина пути посредством чтения / запись. Это не могло бы быть такой проблемой здесь, где у Вас есть чтение того и одна запись op в отдельных потоках, но это - хорошая идея запуститься, поскольку Вы означаете продолжать.

Если, с другой стороны, это - ориентированный на многопотоковое исполнение тип, как CEvent в MFC (или equivilent в повышении) затем, необходимо быть в порядке. Это - лучший подход: используйте ориентированные на многопотоковое исполнение объекты синхронизации для коммуникации межпотока, даже для простых флагов.

11
ответ дан 3 December 2019 в 15:07
поделиться

Вместо того, чтобы использовать членскую переменную, чтобы сигнализировать, что поток сделан, почему бы не использовать a condition? Вы, уже пользуются библиотеками повышения, и condition часть библиотеки потока.

Попробуйте. Это позволяет рабочему потоку 'сигнализировать', что это, закончился, и основной поток может проверить во время выполнения, если условие было сообщено и затем делает то, что это должно сделать с завершенной работой. В ссылке существуют примеры.

Как общий случай я был бы фирн делать предположение, что ресурс будет только изменен потоком. Вы могли бы знать то, для чего это, однако кто-то еще не мог бы - порождение никаких концов горя, поскольку основной поток думает, что работа сделана и пытается получить доступ к данным, которые не корректны! Это могло бы даже удалить его, в то время как рабочий поток все еще использует его и заставляет приложение отказывать. Используя a condition поможет этому.

Взгляд на thread документация, Вы могли также звонить thread.timed_join в основном потоке. timed_join будет ожидать указанной суммы для потока для 'присоединений' (соединение означает, что поток имеет finsihed),

7
ответ дан 3 December 2019 в 15:07
поделиться

Если Вы действительно хотите войти в детали коммуникации между потоками через общую память, даже объявляя, что энергозависимая переменная не будет достаточно, даже если компилятор действительно будет использовать соответствующую семантику доступа, чтобы гарантировать, что это не получит устаревшую версию данных после проверки флага. ЦП может выпустить чтения и пишет не в порядке как долго (x86, обычно не делает, но PPC определенно делает) и нет ничего в C++ 9x, который позволяет компилятору генерировать код для упорядочивания доступов памяти соответственно.

Серия Effective Concurrency Herb Sutter имеет чрезвычайно подробно взгляд на то, как мир C++ пересекает многоядерный/многопроцессорный мир.

5
ответ дан 3 December 2019 в 15:07
поделиться

Я не означаю быть предполагаемым, но кажется, что цель Вашей finished_flag переменной состоит в том, чтобы приостановить основной поток (в какой-то момент), пока поток thrd не завершился.

Самый легкий способ сделать это должно использовать повышение:: поток:: соединение

// launch the thread...
thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag);

// ... do other things maybe ... 

// wait for the thread to complete
thrd.join();
5
ответ дан 3 December 2019 в 15:07
поделиться

При установке потока флаг (или сигнал событие), прежде чем это выйдет, является состоянием состязания. Поток не обязательно возвратился к ОС все же и может все еще выполняться.

Например, рассмотрите программу, которая загружает динамическую библиотеку (псевдокод):

lib = loadLibrary("someLibrary");
fun = getFunction("someFunction");
fun();
unloadLibrary(lib);

И давайте предположим, что эта библиотека использует Ваш поток:

void someFunction() {
    volatile bool finished_flag = false;
    thrd = new boost::thread(boost::bind(&myclass::mymethod, this, &finished_flag);
    while(!finished_flag) { // ignore the polling loop, it's besides the point
        sleep();
    }
    delete thrd;
}

void myclass::mymethod() {
    // do stuff
    finished_flag = true;
}

Когда myclass::mymethod() наборы finished_flag кому: true, myclass::mymethod() еще не возвратился. По крайней мере это все еще должно выполнить какую-то инструкцию "по возврату" (если не намного больше: деструкторы, управление обработчиком исключений, и т.д.). Если выполнение потока myclass::mymethod() предвосхищен перед той точкой, someFunction() возвратится к программе вызова, и программа вызова разгрузит библиотеку. Когда выполнение потока myclass::mymethod() как планируют, будет работать снова, адрес, содержащий инструкцию "по возврату", больше не действителен, и катастрофические отказы программы.

Решение было бы для someFunction() звонить thrd->join() перед возвратом. Это гарантировало бы, что поток возвратился к ОС и больше не выполняется.

2
ответ дан 3 December 2019 в 15:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: