簡體   English   中英

rand_r是否是實線程安全的?

[英]whether rand_r is real thread safe?

好吧,rand_r函數應該是線程安全的函數。 但是,通過其實現,我無法相信它可以使其自身不會被其他線程改變。 假設兩個線程將使用相同的變量種子同時調用rand_r。 因此將發生讀寫競爭。 下面列出了由glibc實現的代碼rand_r。 有人知道為什么rand_r被稱為線程安全嗎?

 int
    rand_r (unsigned int *seed)
    {
      unsigned int next = *seed;
      int result;

      next *= 1103515245;
      next += 12345;
      result = (unsigned int) (next / 65536) % 2048;

      next *= 1103515245;
      next += 12345;
      result <<= 10;
      result ^= (unsigned int) (next / 65536) % 1024;

      next *= 1103515245;
      next += 12345;
      result <<= 10;
      result ^= (unsigned int) (next / 65536) % 1024;

      *seed = next;

      return result;
    }

您可以想到三個線程安全級別,為便於參考,在此將其編號。

1)根本不是線程安全的。 從多個線程同時調用該函數是不安全的。 例如, strtok

2)關於系統的線程安全。 如果不同的調用對不同的數據進行操作,則可以安全地從多個線程同時調用該函數。 例如, rand_rmemcpy

3)關於數據的線程安全。 從多個線程並發調用該函數是安全的,即使作用於同一數據也是如此。 例如pthread_mutex_lock

rand_r處於級別2,在C上下文中的約定(特別是在POSIX規范中)是將其稱為“線程安全”。

在某些其他語言(例如Java)中,慣例是將級別3稱為“線程安全”,而將其他所有內容稱為“非線程安全”。 因此,例如java.util.Vector是“線程安全的”,而java.util.ArrayList是“不是線程安全的”。 當然, java.util.ArrayList所有方法都處於2級。因此,來自Java的程序員自然可以將rand_rmemcpy稱為“不是線程安全的”。

在C語言中,約定有所不同,可能是因為內部同步數據結構開始時很少見。 在C的上下文中,您可能會問“文件句柄是否是線程安全的?”,並且正在談論級別3,但是當詢問“此函數是否是線程安全的嗎?”時,您可能會問。 通常表示2級

rand_r是線程安全的,因為該函數是完全純函數。 除了參數之外,它不會讀取或修改任何狀態。 因此可以安全地同時調用它。

這與大多數將rand (狀態)(狀態)保存在全局變量中的rand函數不同。

假設兩個線程將使用相同的變量種子同時調用rand_r。

我假設你的意思是這樣的

int globalSeed;

//thread 1
rand_r(&globalSeed);

//thread 2
rand_r(&globalSeed);

這並不意味着該函數不是線程安全的,而是意味着您通過提供輸出參數來以非線程安全的方式使用它,該輸出參數可以被另一個線程訪問/修改。

這與將函數結果寫入可以由另一個線程訪問/修改的全局變量相同。 這並不意味着該函數不是線程安全的,這意味着您的代碼不是線程安全的。

因為它修改了種子,所以種子被傳遞了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM