ทุกครั้งที่คุณทำnew Random()
มันจะเริ่มต้นได้โดยใช้นาฬิกา ซึ่งหมายความว่าในวงแคบคุณจะได้รับค่าเท่ากันหลายครั้ง คุณควรเก็บอินสแตนซ์แบบสุ่มเดียวและใช้Next ต่อไปบนอินสแตนซ์เดียวกัน
//Function to get a random number
private static readonly Random random = new Random();
private static readonly object syncLock = new object();
public static int RandomNumber(int min, int max)
{
lock(syncLock) { // synchronize
return random.Next(min, max);
}
}
แก้ไข (ดูความคิดเห็น): ทำไมเราต้องมีlock
ที่นี่?
โดยทั่วไปNext
กำลังจะเปลี่ยนสถานะภายในของRandom
อินสแตนซ์ หากเราทำในเวลาเดียวกันจากหลายเธรดคุณสามารถโต้แย้งว่า "เราเพิ่งทำผลลัพธ์แบบสุ่มมากขึ้น" แต่สิ่งที่เราทำจริง ๆคือการทำลายการใช้งานภายในและเราอาจเริ่มได้รับตัวเลขเดียวกัน จากหัวข้อที่แตกต่างกันซึ่งอาจเป็นปัญหา - และอาจไม่ แม้ว่าการรับประกันว่าสิ่งที่เกิดขึ้นภายในจะเป็นปัญหาที่ใหญ่กว่าก็ตาม เนื่องจากRandom
ไม่ได้รับประกันความปลอดภัยของเธรด ดังนั้นจึงมีวิธีการที่ใช้ได้สองวิธี:
- ซิงโครไนซ์เพื่อให้เราไม่สามารถเข้าถึงได้ในเวลาเดียวกันจากกระทู้ที่แตกต่างกัน
- ใช้
Random
อินสแตนซ์ต่าง ๆต่อเธรด
ทั้งสามารถปรับ; แต่การปิดการใช้งานอินสแตนซ์เดียวจากผู้โทรหลายคนพร้อมกันก็แค่ถามหาปัญหา
lock
ประสบความสำเร็จในครั้งแรก (และง่าย) ของวิธีการเหล่านี้ อย่างไรก็ตามวิธีการอื่นอาจเป็น:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
นี่คือต่อเธรดดังนั้นคุณไม่จำเป็นต้องซิงโครไนซ์
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
ไม่ได้ผลตัวเลข "สุ่ม" ที่ดีไปกว่า.Next(0, 256)