В Интернете можно найти много дискуссий об использовании ключевого слова volatile
в параллельном программировании, иногда с противоречивой аргументацией.Использование флага для связи между потоками
Одно из наиболее заслуживающих доверия обсуждение этой темы - this article by Arch Robison. Примером, который он использует, является задача передачи значения из одного потока в другой:
Нить 1. вычисляет матричный продукт и передает его в Thread 2, что делает что-то другое с ним. Матрица переменной M
и флаг volatile
указатель R
.
- резьбы 1 умножает вычисляет произведение матриц M и атомарно устанавливает R, чтобы указать на М.
- резьбы 2 ждет, пока R! = NULL, а затем использует M в качестве фактора, чтобы вычислить другую матрицу продукта.
Другими словами, M - это сообщение, а R - готовый флаг.
Автор утверждает, что при объявлении R, как летучие будет решить проблему с распространяющимся переходом от Thread 1 до резьбы 2, она не дает никаких гарантий относительно того, что значение М будет, когда это произойдет. И присваивания R
и M
могут быть переупорядочены. Поэтому нам нужно сделать как M
, так и R
volatile или использовать некоторый механизм синхронизации в некоторой библиотеке, такой как pthreads.
Мой вопрос, как сделать следующее в C
1) Как использовать один флаг между двумя потоками - Как атомарно назначить на него, убедитесь, что другой поток будет видеть изменения и тест на изменение в другой теме. Является ли использование волатильности законным в этом случае? Или может ли какая-либо библиотека обеспечить концептуально лучший или более быстрый способ, возможно, с использованием барьеров памяти?
2) Как сделать пример право Робинсона, так как послать матрицу М от одного потока к другому и сделать это безопасно (и, предпочтительно, переносимых с Pthreads)
В ответ на последнее предложение в вашем первом параграфе Энди Робинсон говорит, что обе переменные должны быть volatile для * обеих сторон, так как volatile также предотвратит переупорядочение присвоений флагу и матрице. Но я предполагаю, что вы оставили эту проблему переупорядочения для простоты. – user7610
Матрица, особенно в приложении multiThreaded, где предполагается, что она будет передаваться между потоками, вероятно, будет распределена динамически и поэтому доступна через свой указатель. Указатели обычно имеют размер регистра :( –
Вам нужна изменчивость только на стороне отправителя, если отправитель повторно использует матрицу или указатель. Переупорядочение является самостоятельным вопросом. В качестве статута Necrolis в C11 вы можете использовать _Atomic. – Matthias