[英]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_r
, memcpy
。
3)關於數據的線程安全。 從多個線程並發調用該函數是安全的,即使作用於同一數據也是如此。 例如pthread_mutex_lock
。
rand_r
處於級別2,在C上下文中的約定(特別是在POSIX規范中)是將其稱為“線程安全”。
在某些其他語言(例如Java)中,慣例是將級別3稱為“線程安全”,而將其他所有內容稱為“非線程安全”。 因此,例如java.util.Vector
是“線程安全的”,而java.util.ArrayList
是“不是線程安全的”。 當然, java.util.ArrayList
所有方法都處於2級。因此,來自Java的程序員自然可以將rand_r
和memcpy
稱為“不是線程安全的”。
在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.