2015-02-17 2 views
4

Сценарий выглядит следующим образом: Thread A продолжает выполнение до тех пор, пока не получит сигнал остановки от потока B, который продолжает считывать ввод с консоли.C++ Лучший способ разделить состояние между потоками

Каков наилучший способ реализации этого? Например, я думаю, что я мог бы реализовать его как глобальную переменную, которую поток A проверяет каждый раз, а поток B может меняться на сигнал «stop»,

Но я не знаю, является ли это Правильный способ.

  • Даже если это правильно, я должен использовать "Летучие" или "Atomic <>"? Особенно, что поток A только считывает значение переменной, а поток B записывает только переменную.

  • А что, если изменение переменной из потока B сразу после того, как поток A прочитал, это не имеет значения (не вызывает проблемную нить). Время выключения несколько ослаблено (допускается после сигнала) »)?

  • Есть ли другой способ для нитки B начать нить A и остановить ее, когда она захочет?

+0

Лучший способ обмена данными между потоками - инкапсулировать поток и данные для совместного использования в классе. –

+1

Состояние Не данные, хотя это может не иметь никакого значения –

+0

Что еще означает _state_, чем иметь данные? Также рассмотрите возможность редактирования вашего вопроса. Эта стена текста трудно читать, как есть. –

ответ

5

Вопрос, вероятно, будет закрыт как «слишком широкий», однако я постараюсь ответить на него (в том же «широком» виде).

только можно себе представить ответ здесь: «это зависит» (с)

Некоторые другие примеры того же типа вопросов с той же ответ: Что лучше, есть апельсины или яблоки? Какое лучшее домашнее животное: кошка, собака или черепаха? Лучшая девушка: блондинка, брюнетка или рыжеволосая?

Генеральный совет: Try, и держать его в простой (KISS principle). Начните с простого решения (например, мьютексы в вашем случае), и если вы когда-нибудь найдете его неудовлетворительным, замените его на другую, более сложную, но эффективную/масштабируемую/настраиваемую/приятную вещь (скажем, атомику). Если какое-либо из этих доказательств окажется недостаточным, еще больше усложняйтесь (расслабьте атомы, добавьте блокировку, создайте параллелизм на основе задач, независимо от того, что вам может понадобиться), пока не найдете правильный баланс.

+4

Лучшая девушка явно брюнетка, другие вопросы субъективны. – amdn

+0

@amdn Брюнетки - ненужное промежуточное состояние между блондинками и рыжими. – hyde

+0

@Arno Я бы сказал, что блондинка * и * рыжий - лучший способ получить лучшее из обоих миров ... (и это выходит из-под контроля, я скоро удалю эти сообщения ... :-) – hyde

0

Вы можете использовать переменную, чтобы сигнализировать «стоп», как вы объяснили, но только при условии, что вы используете заграждения памяти.

Для получения более подробной информации см. Understanding c++11 memory fences.

+1

Запонки памяти хуже практически в каждом аспекте по сравнению с замками и атомами в практически любом воображаемом приложении ([подробнее] (http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb -Sutter-atomic-Weapons-1-of-2)) – Drop

1

volatile, вероятно, будет работать, но это не правильное решение. Лучшее, что вы можете сделать, это просто проверить std :: atomic_bool.

2

Вы действительно не хотите останавливать поток, скорее хотите, чтобы он остановил его, когда он находится в хорошем месте.

Это не обязательная глобальная переменная. Вы можете передать адрес структуры в поток. Эта структура может содержать флаг. Если другой поток знал адрес структуры, тогда он мог бы изменить флаг. У вас может быть глобальный массив структур, по одному для каждого потока, который вы используете. Существует множество способов для нескольких потоков работать с одними и теми же данными.

Вы можете использовать сигналы. Они удобны, если поток, который вы хотите закрыть, спал.

Некоторым людям нравится использовать мьютексы и переменные состояния. Другие любят использовать атомные операции. Если вы просто проверяете глобальный int, чтобы узнать, не ноль, мьютекс обычно не нужен.

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

Вы хотите, чтобы глобальность была обнулена перед запуском ваших потоков.

Точно, до наносекунды, когда нить A увидит изменение, это другая проблема. Если поток работает одновременно с потоком B, то он увидит его, как только будет произведено изменение. Если нить А спит, он ничего не увидит. Даже возможный поток B может изменить флаг перед запуском нити A. Когда поток фактически уничтожается, происходит в какое-то неопределенное время после возврата функции потока - всякий раз, когда ОС приближается к ней.

Смежные вопросы