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

У меня есть неизменяемая структура данных, которая представляет собой функциональную хэш-карту (см. fash.scm), которая совместно используется несколько потоков.

Представьте, что поток хочет изменить глобальную хеш-карту на новую версию. Нужна ли мне блокировка для изменения значения? Если это так, я предполагаю, что мне также нужно заблокировать значение для его чтения, не так ли?

Мне кажется, все сводится к тому, является ли установка значения в Scheme атомарной операцией или нет. Согласно этому ответу для языка C, вы должны установить блокировку как для чтения, так и для записи указателя.

Если это важно, я использую хитрость 2.2.3 и bigloo 4.3.


person amirouche    schedule 12.02.2018    source источник
comment
Это немного не по теме для Scheme, поскольку ни один отчет по схеме не поддерживает несколько потоков. Мое лучшее предположение состоит в том, что set! изменяет один указатель, и этот доступ до получения получит старый хеш, а доступ после получит новый. Я не думаю, что у вас будет полумертвый кот между ними.   -  person Sylwester    schedule 13.02.2018


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

person Takashi Kato    schedule 12.02.2018