Каким образом можно установить блокировку (lock) на определенный диапазон значений в структуре данных?

Как реализовать блокировку для диапазона пакетов в udp client-server, вместо блокировки только одного объекта?
  • 27 апреля 2024 г. 6:20
Ответы на вопрос 2
Для установления блокировки на определенный диапазон значений в структуре данных можно использовать мьютексы или семафоры. Мьютексы позволяют блокировать доступ к определенному участку кода или критической секции только одному потоку в определенный момент времени. Семафоры позволяют контролировать количество потоков, которые имеют доступ к определенному участку кода.

Для реализации блокировки для диапазона пакетов в udp client-server, вместо блокировки только одного объекта, можно создать массив мьютексов, где каждому диапазону пакетов будет соответствовать свой мьютекс. При попытке доступа к определенному диапазону пакетов, поток должен запросить доступ к соответствующему мьютексу. При этом другие потоки, пытающиеся обратиться к другим диапазонам, могут работать параллельно без блокировки.

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

Тут "выделение" куска будет не такой тривиальной операцией, как один лок, но зато, никах спинлоков. Система может потоки усипить и будить только когда очередной мютекс освободится.

Если же у вас ожидаются интервалы побольше 100, то тут возможно лучше будет вот такое решение:
У вас будет одна глобальная структура-индекс, где вы будете хранить статус буфера (о ней позже). Потоки будут к ней обращатся и просить у нее выделить потоку кусок.
Внутри этой структуры, похоже, придется сделать один глобальный мьютекс.
В качестве самой структуры хорошо подойдет дерево отрезков с отложенным добавлением . Пусть оно будет считать сумму на отрезке. При запросе на выделение вы смотрите, равна ли сумма на запрошенном отрезке 0. Если да, то прибавляете на отрезке 1. Если нет, то возвращаете неудачу и поток должен будет опять обратиться к структуре. При освобождении интервала прибавляйте -1.

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

Как сделать это без спинлоков с деревом отрезков - я не придумал.
Похожие вопросы