Подтвердить что ты не робот

Является ли блокировка (резьбовая) атомной?

Это может показаться глупым вопросом, но если один задерживает ресурс в многопоточном приложении, то операция, которая происходит на ресурсе, выполняется атомарно?

I.E.: может быть прерван процессор или может произойти переключение контекста, когда на этом ресурсе есть блокировка? Если это произойдет, то ничто другое не сможет получить доступ к этому ресурсу, пока он не вернется к нему, чтобы завершить процесс. Звучит как дорогостоящая операция.

4b9b3361

Ответ 1

Процессор может очень точно переключиться на другой поток, да. Действительно, на большинстве современных компьютеров в любом случае может быть несколько потоков одновременно. Блокировка просто гарантирует, что ни один другой поток не может получить одну и ту же блокировку, поэтому вы можете убедиться, что операция на этом ресурсе является атомарной с точки зрения этого ресурса. Код с использованием других ресурсов может работать совершенно независимо.

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

Ответ 2

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

Ответ 3

Да, может возникнуть контекстный переключатель. Именно поэтому при доступе к совместно используемому ресурсу важно также заблокировать его из другого потока. Когда поток A имеет блокировку, поток B не может получить доступ к заблокированному коду.

Например, если два потока запускают следующий код:

1. lock(l);
2. -- change shared resource S here --
3. unlock(l);

Переключение контекста может произойти после шага 1, но другой поток не может удерживать блокировку в это время и, следовательно, не может изменить общий ресурс. Если доступ к общему ресурсу в одном из потоков выполняется без блокировки - могут случиться плохие вещи!

Что касается расточительности, да, это расточительный метод. Вот почему есть методы, которые пытаются избежать блокировок вообще. Эти методы называются lock-free, а некоторые из них основаны на сильных услугах блокировки, таких как CAS (Compare-And-Swap) или другие.

Ответ 4

Нет, это не очень дорого. Обычно существует только две возможности:

1) У системы есть другие возможности, которые она может сделать: В этом случае система все еще делает полезную работу со всеми доступными ядрами.

2) Системе больше нечего делать: В этом случае поток, содержащий блокировку, будет запланирован. Разумная система не оставит ядро ​​неиспользуемым, пока есть готовый к запуску поток, который не запланирован.

Итак, как это может быть дорого? Если для этой системы нет ничего другого, это не требует приобретения этой блокировки (или недостаточно других вещей, чтобы занять все ядра), и поток, удерживающий блокировку, не готов к запуску. Так что случай, который вам нужно избегать, и проблема переключения контекста или проблемы с предварительным выпуском не имеют значения (поскольку поток будет готов к запуску).