For a fine-grained commit, use an array of read / write locks (as suggested by Carey Hickling). Hash the index value and filter it through a bitmask (or use a module) to choose which lock to use.
This effectively splits the indices into N buckets, where N is the number of locks you create. Select the number of two locks to quickly block the bits (mask = N - 1). The only drawback of this scenario is that you are not just blocking a specific index, you are blocking every index that, when hashed, aligns with the same lock pointer.
Thus, the more locks you create, the larger the granular lock (16 is probably a good starting point). Reading locks is also used with rw_locks, so you only need to worry about waiting for a lock while writing.
source share