2010-02-16 16 views
25

有人能告訴我哪些代碼可以稱爲「重入」代碼?什麼樣的代碼可以稱爲「重入」?

閱讀一些實時操作系統,當我遇到這個詞來了。爲了使代碼成爲「重入」代碼,必須堅持哪些規範?

+3

奇怪的是,第一個谷歌命中:http://en.wikipedia.org/wiki/Reentrant_(subroutine) – 2010-02-16 16:09:43

+0

@Mitch,如果有人摘錄與RTOS相關的位,則將其重新命名並使其專用於「學科必須堅持「這個問題的位,然後希望第一次谷歌命中將成爲這個問題,因此,我們都想要的,對吧? =) – Rob 2010-02-16 16:10:51

+0

@Rob:也許。這很難說..... – 2010-02-16 16:12:52

回答

41

一般來說,代碼重入塊是一個可以由其他演員之前更早的調用完成後,在不影響第一男主角會通過代碼的路徑輸入。也就是說,有可能重新輸入代碼,而它已經在運行,並且仍然產生正確的結果。

在大多數情況下,「演員」是同一過程的線程,但thread safety和重入的概念是微妙的不同:不是每個線程安全塊重入的,但每一個重入塊是線程安全的。也就是說,重入性比線程安全性更強。這裏的a good example來自Raymond Chen的一段代碼可能是線程安全的,但不可重入。

有一個特殊的情況下,當代碼是遞歸的:同一演員調入代碼自身的調用完成之前,如馬克·Gravell指出。所有正確的遞歸塊都是可重入的;當然,並不是每個重入塊都是遞歸的。

+0

感謝所有的答覆,但是,我只能標記1個答覆作爲答案。對不起,那個..:D – smwikipedia 2010-02-22 05:56:48

+1

並非所有的遞歸塊都是可重入的。在一些8x51編譯器上,局部變量存儲在靜態地址中。可遞歸調用的例程具有「正在使用」標誌;如果例程在設置「正在使用」標誌時進入,則它會將其變量複製到堆棧並清除該標誌。在例程發出可能遞歸的調用之前,它會設置「正在使用」標誌;一旦這個調用返回,如果該標誌沒有被設置,那麼這個例程重新從堆棧中加載它的變量。以這種方式編碼的例程支持遞歸,但不能重入。 – supercat 2012-05-15 15:38:54

+2

_「...但是每個重入塊都是線程安全的。」_你介意看一看[關於重入的維基百科條目](http://en.wikipedia.org/wiki/Reentrancy_%28computing% 29)?因爲有一個函數的例子是可重入的,但不是線程安全的。編輯是否有可能犯了一個錯誤?謝謝。 – 2014-07-07 11:47:03

1

另一個線程可以調用的代碼,而第一個線程在運行它的中間?如果代碼產生一個回調函數,回調函數在第一個runthrough完成之前是否可以調用代碼?

如果代碼使用的未鎖定的全局變量,還是有它自己的靜態瓦爾,它並沒有採取特別的預防措施有,任何這些情況可能會打破它。

9

幾乎任何類型的遞歸代碼可以被歸類爲重入(即你可以調用回相同的方法,無需在完成它),但是這是在談論鎖,互斥鎖,信號等。當使用特別例如,鎖是可重入,如果一旦你有鎖可以再次成功「鎖定」的代碼(即你不死鎖自己) - 例如:

public void AddIfNecessary(string s) { 
    lock(syncObj) { 
     if(!Contains(s)) Add(s); 
    } 
} 

public void Add(string s) { 
    lock(syncObj) { 
     list.Add(s); 
    } 
} 

public bool Contains(string s) { 
    lock(syncObj) { 
     return list.Contains(s); 
    } 
} 

這裏的事實鎖是可重入的意思是我們可以撥打ContainsAdd而不用擔心我們已經有了「ex聚合「鎖,使代碼更簡單。在內部,使用計數器而不是簡單的「使用中」標誌。

10

約翰Feminella的回答說:

的代碼可重入塊是一個 可以由另一個演員 較早調用完成之前輸入。 也就是說,有可能在代碼已經運行時重新輸入 。

但是,對於非重入代碼塊也是如此。如果代碼塊已經寫入而不考慮這個問題,第二個演員仍然可以同時輸入代碼塊。

的問題是,這對任何調用的結果有什麼影響。因此,更準確:可重入塊是一個可以由另一名演員的早期調用結束前輸入,而不改變任何一個調用的結果

既不調用應該能夠檢測其它的「存在」。

+2

直到現在我才注意到這個答案!感謝您的澄清;你是對的,我可以更具體。我會相應修改。 – 2012-04-26 18:41:02

0

一種計算機程序,被稱爲重入,如果它能夠在其執行過程中被中斷,然後安全地以前的調用完成執行之前再次調用。中斷可能由內部動作(如跳轉或調用)引起,或者由外部動作(如硬件中斷或信號)引起。重新進入的調用完成後,先前的調用將恢復正確的執行。

+0

添加參考維基百科? http://en.wikipedia.org/wiki/Reentrant_(subroutine) – greeness 2012-10-22 02:06:53

3

重入代碼,當頁面都有一個共同的資源和資源不應該被改變或操縱。然後這個資源被稱爲重入代碼或純代碼。

可以通過並行運行不同的線程調用
1

代碼。所以,代碼:

  1. 可以局部變量(每個線程的堆棧上分配)
  2. 應該有守衛全局和靜態變量,因爲線程將分享他們將會有一場比賽條件在這裏。
0

非折返示例

class Test { 
    int count; 

    // Here method1() is not reentrant 
    int method1() 
    { 
     return count + 1; 
    } 
} 

折返例如

class Test { 
    int count; 

    // Here method1() is reentrant 
    int method1(int count) 
    { 
     return count + 1; 
    } 
} 
0

簡單地說,一個可重入代碼是可以多個處理之間共享的碼。

在同時滿足下列條件時,這是可能的:

  1. 它不應該有全局和靜態數據。
  2. 它不應該修改它自己的代碼。
  3. 它不應該調用另一個重入函數或代碼段。

所以,以下這些條件代碼可以被稱爲重入代碼。

+0

我覺得這不太對。共享對象中的例程確實滿足第二個和第三個條件,但它們確實具有全局和靜態數據,並且它們基於您的定義重入,因爲它們在許多進程之間共享。 – 2017-07-10 08:04:35

相關問題