I'm trying to implement a read-write lock, and I was told to use boost::upgrade_lock. However, only one thread can have a boost::upgrade_lock, and everyone else gets blocked, so it's not much on the read end. (Correct me if I am wrong, but boost::upgrade_lock only waits if someone has exclusive, but someone with boost::upgrade_lock will cause everyone else to block) But reads are cheap in my case - I just need to use locks for a cache. So, suppose I have the following: class Cache { std::map cache; boost::shared_mutex mutex; public: Output query(const Input& in); }; It would appear that the proper way to implement Cache::query() is as follows: Output query(const Input& in) { boost::shared_lockboost::shared_mutex readLock(mutex); if (cache.count(in) == 0) { readLock.unlock(); boost::unique_lockboost::shared_mutex writeLock(mutex); // Check to see if the result was added while waiting for lock if (cache.count(in) != 0) return cache[in]; cache[in] = compute_output(in); return cache[in]; } else { return cache[in]; } } Is this correct? Or maybe it should be this: Output query(const Input& in) { boost::shared_lockboost::shared_mutex readLock(mutex); if (cache.count(in) == 0) { readLock.unlock(); boost::upgrade_lockboost::shared_mutex rereadLock(mutex); // Check to see if the result was added while waiting for lock if (cache.count(in) != 0) { return cache[in]; } else { boost::upgrade_to_unique_lockboost::shared_mutex writeLock(rereadLock); cache[in] = compute_output(in); return cache[in]; } } else { return cache[in]; } } A side question is that if compute_output() is an expensive operation, should that be moved to the part between releasing the read lock and getting the write/reread lock?