Нужна ли блокировка для доступа к неизменяемой структуре данных в контексте многопоточности?
У меня есть неизменяемая структура данных, которая является функциональной хэш-картой (см. Fash.scm), которая используется несколькими потоками.
Представьте, что поток хочет изменить глобальную хэш-карту на новую версию. Нужна ли блокировка для изменения значения? Если это так, я предполагаю, что мне также нужно заблокировать значение, чтобы прочитать его, не так ли?
Мне кажется, это сводится к тому, является ли установка значения в Схеме атомарной операцией или нет. Согласно этому ответу для языка Си, вы должны получить блокировку как для чтения, так и для доступа к указателю.
Если это имеет значение, я использую guile 2.2.3 и bigloo 4.3.
1 ответ
Все зависит от того, что вы хотите сделать. В общем случае, если значение может быть гарантировано прочитано (например, всегда число), то можно не блокировать при чтении значения. Например,
(import (rnrs) (srfi :18))
(define count 0)
(define t
(thread-start!
(make-thread
(lambda ()
(let loop ()
(display count) (newline)
(thread-sleep! 0.1)
(loop))))))
(do ((i 0 (+ i 1))) ((= i 10))
(set! count (+ count 1))
(thread-sleep! 0.1))
Это довольно безопасно читать. Однако, если это значение, скажем, вектор длины 1, то вы можете заблокировать, если другие потоки могут изменить значение на #f или вектор длины 0. Например:
(import (rnrs) (srfi :18))
(define count (vector 1))
(define t
(thread-start!
(make-thread
(lambda ()
(let loop ()
(display (vector-ref count 0)) (newline)
(thread-sleep! 0.1)
(loop))))))
(do ((i 0 (+ i 1))) ((= i 10))
(vector-set! count 0 (+ (vector-ref count 0) i))
(thread-sleep! 0.1))
(set! count #f) ;; if this happens, the you may want to lock on reader thread
Я не проверял, как реализован fash, но пока записи не обновляются до неожиданных значений, я думаю, что можно не блокировать.