'How to fill a Map thread safe in a lazy manner?

Suppose you have a Map (programming language doesn't matter) and would like to fill it up bit by bit. Can someone show how to make this thread-safe (parallel reads, exclusive writes) given a read-write lock object is available?

Here's some pdeudo-code, which is not threadsafe, to get started:


def get_or_create_item(item_id)
  if ([email protected]_key?(item_id))
    @map[item_id] = create_item()
  end
  return @map[item_id]
end

def create_item
  #...
end

How to make it thread-safe, assuming you have a read-write lock object available?

rw_lock = ReadWriteLock.new
...
rw_lock.acquire_read()
rw_lock.release_read()
...
rw_lock.acquire_write()
rw_lock.release_write()

Thanks



Solution 1:[1]

Pseudocode with a read-write lock object would look like this:

ReaderWriterLock rwLock // initially unlocked

getOrCreate(id)
    // try getting
    rwLock.acquireRead()
    optional res = map[id]
    rwLock.releaseRead()
    if (res.hasValue)
        return res

    // since we are here, the item isn't in the map
    rwLock.acquireWrite()
    res = map[id]
    // check again if another thread inserted the item while we were waiting for the write lock
    if (!res.hasValue)
        res = createItem()
        map[id] = res
    rwLock.releaseWrite()
    // at this point res must have a value
    return res            

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sergey Kalinichenko