All Manuals > LispWorks® User Guide and Reference Manual > 19 Multiprocessing

19.5 Modifying a hash table with multiprocessing

Each hash-table access operation is thread-safe and atomic, but there is no guarantee of atomicity between access operations.

The modify macros (for example incf) all expand to two access operations, reading the value and writing the modified value, and are therefore not atomic. They need to be either done while holding a lock, or using modify-hash.

Another common operation is "ensuring an entry", that is reading and, if reading fails, adding a value to the table. For example:

(or (gethash key hash-table)
    (setf (gethash key hash-table) (construct-new-value)))

If two threads do that in parallel, one of them may end up with a value that is not in the table. One solution is to lock that table:

(with-hash-table-locked hash-table
  (or (gethash key hash-table)
      (setf (gethash key hash-table) (construct-new-value))))

However that always locks the table, which is inefficient. The correct way to do it is either to do:

(or (gethash key hash-table)         ; first try without the lock
    (with-hash-table-locked hash-table
      (or (gethash key hash-table)   ; check again inside the lock
          (setf (gethash key hash-table) (construct-new-value)))))

or use gethash-ensuring or with-ensuring-gethash.

LispWorks® User Guide and Reference Manual - 01 Dec 2021 19:30:21