Не злоупотребляйте критическими секциями

Критическая секция — это блок кода, который не может выполняться более чем одним процессом/потоком одновременно, поэтому критические секции дороги и могут привести к «бутылочному горлышку» производительности на определенном потоке.

Критические секции должны быть максимально короткими, простыми (если возможно) и эффективными.

Например, рассмотрим следующий блок кода, который генерирует новый UUID для общего объекта:

with self._mutex:
    # start of lock 
    try:
        self._action.id = str(uuid.uuid4())                      
        self._logger.trace("action generated, action_id={action_id}".format(action_id=self._action.id))
    except BaseException as err:
        self._logger.error(err,"failed to generate uuid")
    # end of lock
Вход в полноэкранный режим Выход из полноэкранного режима

Здесь я допустил три распространенные ошибки:

  1. try & catch, хорошо, я признаю это, возможно, не самая распространенная ошибка, поскольку никто не будет помещать try & catch, который может находиться за пределами критической секции, внутрь нее без веской причины.
  2. ведение журнала внутри критической секции. Обычно логирование — это дорогая операция ввода-вывода, которую можно было бы выполнить вне критической секции.
  3. генерация UUID внутри критической секции

Вот другой блок кода, который делает то же самое, только без этих трех ошибок:

try:
    action_id = str(uuid.uuid4())
    with self._mutex:
        # start of lock
        self._action.id = action_id                  
        # end of lock

    self._logger.trace("action generated, action_id={action_id}".format(id=action_id))  
except BaseException as err:
    self._logger.error(err,"failed to generate uuid")
Вход в полноэкранный режим Выход из полноэкранного режима

Когда вы используете блокировку, помните, что ее цель — избежать одновременного доступа нескольких потоков к общим ресурсам

Оцените статью
Procodings.ru
Добавить комментарий