2010-01-22 2 views
5

Вот несколько C++-кода, к которым обращаются из нескольких потоков параллельно. Он имеет критический раздел:Задание переупорядочения с помощью замков

lock.Acquire(); 
current_id = shared_id; 
// small amounts of other code 
shared_id = (shared_id + 1) % max_id; 
lock.Release(); 
// do something with current_id 

Класс переменной блокировки является оберткой вокруг реализации мьютекса POSIX. Из-за работы модуля невозможно использовать атомные операции.

Возможно ли, что gcc-компилятор с флагом O3 оптимизирует код так, чтобы назначение current_id было перемещено перед блокировкой?

ответ

3

Можно скомпилировать с помощью O3!

Компилятор никогда не будет оптимизировать функцию вызова функции, если функция не будет отмечена как чистая с использованием атрибутов функции.

Функции мьютекса не являются чистыми, поэтому абсолютно безопасно использовать их с O3.

+1

Вы имеете в виду «если функция не помечена как чистая **, или компилятор может определить, что это безопасно». Конечно , конечный результат тот же, компилятор не будет делать оптимизацию вообще, если только он не может проверить, что он безопасен. – jalf

+0

Если 'current_id' и' shared_id' являются локальными переменными, которые не экранировали текущую область (адрес не был предоставлен никому другому и т. д.), тогда оптимизатор мог бы переупорядочить эту строку, не учитывая возможную мутацию из внешних вызовов функций. Я предполагаю, что здесь не так. – ephemient

+0

@ephemient: но если они локальные и нет один из них знает о них, как может их изменить внешний вызов? – Kosi2801

1

Обычно компилятор не должен производить такую ​​вредную оптимизацию. Если вы все еще не уверены, вы можете использовать ключевое слово volatile, чтобы предотвратить оптимизацию этих переменных id.

+0

volatile не предотвращает всех соответствующих оптимизаций. Это предотвращает кэширование значения в регистре, но почти ничего больше. Чтение/запись все еще можно изменить. – jalf

+0

Хорошее отношение к использованию летучих, как часть документации ядра Linux: http://www.mjmwired.net/kernel/Documentation/volatile-considered-harmful.txt – asveikau

+0

@jalf: но компиляторы действительно изменяют порядок чтения/пишет, чтобы они пересекали границы функций-вызовов? Назначения и вызовы функций, смешанные между собой, довольно распространены, и я думаю, что во всем мире было бы много проблем, если бы выбор переменных мог переключать порядок с вызовами функций. – Kosi2801

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