Let's say I have a multithreaded C++ program that handles requests in the form of a function call to handleRequest(string key)
. Each call to handleRequest
occurs in a separate thread, and there are an arbitrarily large number of possible values for key
.
I want the following behavior:
- Simultaneous calls to
handleRequest(key)
are serialized when they have the same value forkey
. - Global serialization is minimized.
The body of handleRequest
might look like this:
void handleRequest(string key) {
KeyLock lock(key);
// Handle the request.
}
Question: How would I implement KeyLock
to get the required behavior?
A naive implementation might start off like this:
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.
}
...but that requires a global lock at the beginning and end of each request, and the creation of a separate Lock
object for each request. If contention is high between calls to handleRequest
, that might not be a problem, but it could impose a lot of overhead if contention is low.