跳轉到內容

Ruby 程式設計/參考/物件/執行緒

來自華夏公益教科書,開放的書籍,開放的世界

執行緒

[編輯 | 編輯原始碼]

Ruby 中的 Thread 類是一個包裝器/幫助程式,用於操作執行緒(啟動它們、檢查狀態、儲存執行緒區域性變數)。

這裡是一個很好的教程。

請注意,對於 MRI 1.8,Ruby 使用“綠色執行緒”(偽執行緒 - 實際上是單執行緒)。對於 1.9,MRI 使用“帶全域性直譯器鎖的原生執行緒”,因此“通常是單執行緒的”。Jruby 使用真正的併發執行緒。IronRuby 使用真正的併發執行緒。Rubinius 目前與 MRI 1.9 類似。見這裡以獲得良好的背景。

因為 1.8 使用綠色執行緒,這意味著對於 Windows,任何“C”呼叫(如 gets、puts 等)都會阻塞所有其他執行緒,直到它返回。排程程式只能在執行 Ruby 程式碼時從一個執行緒切換到另一個執行緒。但是,您可以在一個執行緒中執行子程序,它將起作用,並且您可以執行 select,它仍然能夠線上程之間切換。對於 Linux,這意味著您可以選擇 $stdin,因此不會阻塞輸入。但是,對於 Windows,您真的被卡住了。任何鍵盤輸入都會阻塞所有其他執行緒。在 1.9 中,由於使用原生執行緒(執行 IO 呼叫的執行緒在 IO 呼叫返回之前釋放對 GIL 的控制),這個問題不再那麼嚴重。您可以使用 Jruby[1] 對於非阻塞 1.8。

在 1.9 中,您可以透過將 C 呼叫包裝在 rb_thread_blocking_region 中來“繞過”全域性執行緒鎖(這將基本允許該執行緒“執行並完成其任務”,而其他 Ruby 執行緒仍然以一次一個的方式執行。當方法返回時,它將再次進入 Ruby 環境,併成為“全域性鎖定”(一次一個)執行緒之一)。

執行緒區域性變數

[編輯 | 編輯原始碼]

如果您想用一個特定於該執行緒的特定引數啟動一個執行緒,您可以使用 Thread.current

Thread.new { 
  puts Thread.current # unique!
}

或者您可以用一個引數啟動它,比如

th = Thread.new(33) {|parameter|
  thread_unique_parameter = parameter
}

這避免了在啟動執行緒時出現併發問題,例如

# BROKEN
for x in [1,2,3] do
 Thread.new {
   puts x # probably always outputs 3 because x's value changes due to the outside scope
 }
end


在多個執行緒上連線

[編輯 | 編輯原始碼]

對於這種情況,使用 ThreadsWait

require 'thwait'
ThreadsWait.join_all(th1, th2, th3) do |th_that_just_exited| # could also call it like join_all([th1, th2, ...])
  puts 'thread just exited', th_that_just_exited
end
# at this point they will all be done

控制併發

[編輯 | 編輯原始碼]

請參閱Mutex 類瞭解如何控制執行緒之間的互動。

  1. http://betterlogic.com/roger/?p=2930
華夏公益教科書