在Web服務器上,許多線程正在將內容提供給客戶端。 A/B測試是在網站上執行的,所以我們需要PRNG爲每個會話和測試選擇一個變體。 顯然,當使用PRNG的單個實例時,它將被同時訪問,因此可能需要適當的鎖定或其他機制。Java中的併發隨機數生成
最初我們使用java.util.Random
(juR),但由於它有缺陷提到例如How good is java.util.Random,我們試着用MersenneTwister代替。 然而,由於Mersenne-Twister relies on an internal state這一事實,我們看到性能大幅下降,所以它需要同步nextInt()
的訪問權限。 另一種選擇可能是異或移位PRNG,但它與Mersenne Twister具有相同的問題。 你可以找到一個解釋,例如這裏:http://xorshift.di.unimi.it/
Random
uses a compareAndSet操作,它似乎更快,因爲它不需要鎖定,但根據類Javadoc它仍然不是線程安全的。相反,建議使用ThreadLocalRandom
,這基本上會導致PRNG池。根據請求,隨機可用線程處理HTTPS請求,因此從一組可用的PRNG中選擇一個隨機PRNG。顯然這很快。
從這樣的池中產生的隨機數與單個PRNG實例中的一樣好嗎?
另一種方法是使用單個PRNG實例從它預先生成一個值流,例如,通過使用ArrayBlockingQueue
。
哪種解決方案在性能方面效果更好?
對於這個應用程序(選擇A或B是否顯示給用戶),只要它們是均勻分佈的,隨機數的質量並不重要。 – Henry
您正在預先優化。 Random被記錄爲線程安全的,並且與Web應用程序所需的所有IO(數據庫查詢,HTTP請求等)相比,每次啓動會話時調用nextBoolean()的性能完全可以忽略不計。 –
這個想法試圖在隨機數質量方面提出比java.util.Random更好的東西。實際上我們不止有兩個變體,所以我們繪製整數。 @Henry據我所讀,Random中位數的概率並不是均勻分佈的。 – user3001