可重入

可重入

若一個程序子程序可以“安全的被並行執行(Parallel computing)”,則稱其爲可重入(reentrant或re-entrant)的。即當該子程序正在運行時,可以再次進入並執行它(並行執行時,個別的執行結果,都符合設計時的預期)。若一個函數是可重入的,則該函數:

  • 不能含有靜態(全局)非常量數據。
  • 不能返回靜態(全局)非常量數據的地址。
  • 只能處理由調用者提供的數據。
  • 不能依賴於單實例模式資源的鎖。
  • 不能調用(call)不可重入的函數(有呼叫(call)到的函數需滿足前述條件)。

多“用戶/對象/進程優先級”以及多進程,一般會使得對可重入代碼的控制變得複雜。同時,IO代碼通常不是可重入的,因爲他們依賴於像磁盤這樣共享的、單獨的(類似編程中的靜態(Static)、全域(Global))資源。

可重入性是函數編程語言的關鍵特性之一。

在以下的C語言代碼中,函數f和函數g都不是可重入的。

int g_var = 1;

int f()
{
  g_var = g_var + 2;
  return g_var;
}

int g()
{
  return f() + 2;
}

以上代碼中,f使用了全局變量 g_var,所以,如果兩個線程同時執行它並訪問g_var,則返回的結果取決於執行的時間。因此,f不可重入。而g調用了f,所以它也不可重入。

稍作修改後,兩個函數都是可重入的:

int f(int i)
{
  return i + 2;
}

int g(int i)
{
  return f(i) + 2;
}

與線程安全的關係

可重入與線程安全兩個概念都關係到函數處理資源的方式。但是,他們有一定的區別。可重入概念會影響函數的外部接口,而線程安全只關心函數的實現。

  • 大多數情況下,要將不可重入函數改爲可重入的,需要修改函數接口,使得所有的數據都通過函數的調用者提供。
  • 要將非線程安全的函數改爲線程安全的,則只需要修改函數的實現部分。一般通過加入同步機制以保護共享的資源,使之不會被幾個線程同時訪問。

因此,相對線程安全來說,可重入性是更基本的特性,它可以保證線程安全:即,所有的可重入函數都是線程安全的,但並非所有的線程安全函數都是可重入的。

 

轉自:http://zh.wikipedia.org/wiki/%E5%8F%AF%E9%87%8D%E5%85%A5

發佈了18 篇原創文章 · 獲贊 27 · 訪問量 13萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章