2014-05-23 166 views
1

據我所知,有可能只獲取當前線程內的部分來電/回溯信息; (在創建當前線程的線程中)之前的任何內容都會被截斷。以下舉例說明這一點。它創建了一個名爲d線程的事實,a稱爲b,呼籲c,被切斷:超出線程的來電/回溯

def a; b end 
def b; c end 
def c; Thread.new{d}.join end 
def d; e end 
def e; puts caller end 

a 
# => this_file:4:in `d' 
# this_file:3:in `block in c' 
  1. 什麼是此功能的原因是什麼?
  2. 有沒有辦法讓主叫/回溯信息超出當前線程?

回答

0

這兩個問題的答案都是一樣的。考慮一個稍微涉及的主線程。與其簡單地等待產生的線程在c內結束,主線程繼續調用其他函數,甚至可能從c返回並開始它的業務,而產生的線程繼續關於它的業務。

這意味着自生成d開始的線程以來,主線程中的堆棧已更改。換句話說,在您撥打puts caller時,主線程中的堆棧不再處於創建輔助線程時的狀態。超越這一點,沒有辦法安全地走回堆棧。

因此,在短期:

  1. 產卵線程的堆棧將不會留在它是當線程被催生了這樣走回到超出線程自己的堆棧是不是安全的起始狀態。

  2. 不,因爲線程背後的整個想法是(僞)並行,所以它們的堆棧是完全不相關的。

更新:

正如意見提出,當前線程的堆棧可以被複制到在創建時新的線程。這將保留導致正在創建線程的信息,但解決方案並非沒有自己的一套問題。

  1. 創建線程會變慢。如果有什麼可以從中獲益的話,那也可以,但在這種情況下,是嗎?

  2. 從線程輸入函數返回什麼意思?

    • 它可以返回到創建線程的函數並繼續運行,就好像它只是一個函數調用一樣 - 只是它現在在第二個線程中運行,而不是原來的運行。我們想要那個嗎?
    • 可能有一些魔法確保線程終止,即使它不在調用堆棧的頂部。這會使線程入口函數上方的調用堆棧中的信息不正確。
  3. 對於每個線程的stacksize有限制的系統,如果線程沒有使用太多的線程,可能會遇到問題。

有可能其他場景以及可以深思熟慮過的特殊性,但線程的方式與自己的空棧入手,使模型既簡單且可預測的沒有留下任何有用的信息進行調用堆棧的創建。

+0

您的答案解釋了爲什麼當前實現無法返回信息。但我原則上認爲這是不可能的。如果每個線程在其創建時複製調用者信息直到它創建的位置,並將其保存在其自身內部,那麼是否有可能從該線程中獲取整個信息?我錯了嗎?我覺得我甚至可以在Ruby級別實現它。 – sawa

+0

沒有什麼是不可能的,但是有什麼可以獲得的? Se更新了答案。 – harald

0

我想我想出了我的答案。

可以從線程外部完成線程的事情不僅僅是創建它。除了創建之外,您可以喚醒等。因此,不清楚應將哪些操作歸入調用者。例如,假設有一個線程:

1: t = Thread.new{ 
2: Thread.stop 
3: puts caller 
4: } 
5: t.wakeup 

線程t在第1行創建的,但在第2行進入睡眠本身,則通過線5醒來所以,當我們找到自己在第3行caller,並考慮線程外的呼叫者部分,不清楚第1行中的Thread.new應該是其中的一部分,還是第5行中的t.wakeup應該是其中的一部分。因此,在當前線程之外沒有明確的概念呼叫者。

但是,如果我們定義一個清晰的概念,那麼調用者可能超出一個線程是有意義的。例如,總是將調用者添加到創建線程中可能是有道理的。否則,添加導致最近的wakeup或創建的呼叫者可能是有道理的。這取決於定義。