Нужна ли блокировка для доступа к неизменяемой структуре данных в контексте многопоточности?

У меня есть неизменяемая структура данных, которая является функциональной хэш-картой (см. 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, но пока записи не обновляются до неожиданных значений, я думаю, что можно не блокировать.

Другие вопросы по тегам