[ruby 的多工]Queue v.s. Thread ? & Mutex ...


#1

在試怎同時跑多個 process…

看了舊文

和官網的 thread v.s. Queue…

理解的是…

弄一個工作的 queue (一般是 array )…把工作 queue 丟進去…

有個 worker 去解 queue …(這是 thread ?)

然後如果會有共同的資料(e.g. db/變數…) 怕同時修改就有個 lock 的功能…就是 mutex…

但在官網中…
thread v.s. Queue 這二個東西…
都有點好像混在一起的感覺…
就是說如果 Queue 是一個排序(用一個 array 去丟入+丟出…)
那 Queue.new 的用途是?

有稍為更詳細的 demo 嗎?..(還是個人理解錯誤?..)

謝謝


#2

這邊修正一下幾個名詞解釋,因為 Thread vs Queue 兩個單位不同無法一起比較

Process : 運行中的主程式,可用多核CPU,有自己的變數空間,因為記憶體空間不一樣,但可以用類似 stdout / socket 的方式來做溝通(就是另外開 port 另外做)而 subprocess 的話很簡單,類似 system / open3 都是開 subprocess 的方式,好處:一個噴了不會連主程式一起噴,尤其是 kernel 等級的錯誤

Thread:運行中的主程式下的子程式,可用多核CPU,和主程式及其他子程式變數空間相同,但因為相同所以就要開始考慮 race condition 的問題,其實 process 也會發生 race condition,不過那是針對其他服務,類似 RDBMS,但是 thread 發生的 race condition 是發生在程式內部

再來是 Queue,Queue 真正的實作其實是 Mutex + Array,所以可以先看成 Queue == Array,只不過自動附加了 Mutex 的保證,以下簡單的問題

$x = 0
100.times do
  Thread.new do
    100.times do
      if $x > 0
        sleep(rand / 100)
        $x -= 1
      else
        sleep(rand / 100)
        $x += 1
      end
    end
  end
end
sleep(10)
puts $x

用 irb 執行,最後結果應該不會是 0,而用 pry 好像有強迫上 semaphore 所以不準,而範例二加四行就好

require 'thread'
$semaphore = Mutex.new
$x = 0
100.times do
  Thread.new do
    100.times do
      $semaphore.synchronize do
        if $x > 0
          sleep(rand / 100)
          $x -= 1
        else
          sleep(rand / 100)
          $x += 1
        end
      end
    end
  end
end
sleep(20)
puts $x

這是說明 race condition 最簡單的例子,如果 single thread / process 只要沒有達到 thread safe 基本上就會出事,而 mutex 真正的意義是 semaphore + synchronize,後面想要共用資源的必須排隊,也就是範例二會需要 sleep 兩倍時間的原因就是

相同的如果對 Array 做操作,也就是你說的 Queue

@object = rand > 0.5 ? Array.new : Queue.new
@object.push(A)
@object.shift
@object.push(B)
@object.shift

在 multi thread 的狀況下,這四行可能不是照順序來,可能會錯置的操作,甚至別人會取到明明已經 shift 出去不要的物件,所以比較高級的操作甚至直接取代掉變數所指的物件,每次都使用新的物件,所以我曾經的某個作品有用到這個 Gem 來做 thread safe 的保證

anyway 這邊這一整票可能需要操作比較大的 multi-thread 的系統,且高頻交易,不知道哪裡出問題然後想辦法把所有東西都上了 thread safe 後解光了才比較有感就是了

multi-tread 發生的 race condition 一直都是"處理共用資源"下才會發生的,所以如果你都是 local variable,且所有東西不共用下,使用外部服務操作也不用管 lock 的問題時,自然不會感受到 race condition 發生的問題就是,以上