Допустим, у меня есть многопоточная программа C ++, которая обрабатывает запросы в виде вызова функции handleRequest(string key)
. Каждый вызов handleRequest
происходит в отдельном потоке, и существует произвольно большое количество возможных значений для key
.
Я хочу следующее поведение:
- Одновременные вызовы на
handleRequest(key)
сериализуются, когда они имеют одинаковое значение для key
.
- Глобальная сериализация сведена к минимуму.
Тело handleRequest
может выглядеть так:
void handleRequest(string key) {
KeyLock lock(key);
// Handle the request.
}
Вопрос: Как мне реализовать KeyLock
, чтобы получить требуемое поведение?
Наивная реализация может начинаться так:
KeyLock::KeyLock(string key) {
global_lock->Lock();
internal_lock_ = global_key_map[key];
if (internal_lock_ == NULL) {
internal_lock_ = new Lock();
global_key_map[key] = internal_lock_;
}
global_lock->Unlock();
internal_lock_->Lock();
}
KeyLock::~KeyLock() {
internal_lock_->Unlock();
// Remove internal_lock_ from global_key_map iff no other threads are waiting for it.
}
... но для этого требуется глобальная блокировка в начале и конце каждого запроса и создание отдельного объекта Lock
для каждого запроса. Если между вызовами на handleRequest
велика конкуренция, это может не быть проблемой, но это может привести к большим накладным расходам, если конкуренция низкая.