Mỗi khi bạn làm điều new Random()
đó được khởi tạo bằng đồng hồ. Điều này có nghĩa là trong một vòng lặp chặt chẽ, bạn nhận được cùng một giá trị rất nhiều lần. Bạn nên giữ một thể hiện ngẫu nhiên duy nhất và tiếp tục sử dụng Next trên cùng một thể hiện.
//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);
}
}
Chỉnh sửa (xem bình luận): tại sao chúng ta cần một lock
ở đây?
Về cơ bản, Next
sẽ thay đổi trạng thái nội bộ của Random
thể hiện. Nếu chúng tôi làm điều đó cùng một lúc từ nhiều luồng, bạn có thể lập luận rằng "chúng tôi vừa tạo ra kết quả thậm chí còn ngẫu nhiên hơn", nhưng những gì chúng tôi thực sự đang làm có khả năng phá vỡ việc thực hiện nội bộ và chúng tôi cũng có thể bắt đầu nhận được những con số tương tự từ các chủ đề khác nhau, có thể là một vấn đề - và có thể không. Tuy nhiên, sự đảm bảo cho những gì xảy ra trong nội bộ là vấn đề lớn hơn; kể từ khi Random
nào không thực hiện bất kỳ sự bảo đảm của thread-an toàn. Do đó, có hai cách tiếp cận hợp lệ:
- Đồng bộ hóa để chúng tôi không truy cập cùng lúc từ các luồng khác nhau
- Sử dụng các
Random
trường hợp khác nhau cho mỗi luồng
Hoặc là có thể tốt; nhưng việc tạo ra một trường hợp duy nhất từ nhiều người gọi cùng một lúc chỉ là vấn đề.
Việc lock
đạt được đầu tiên (và đơn giản hơn) của các phương pháp này; tuy nhiên, một cách tiếp cận khác có thể là:
private static readonly ThreadLocal<Random> appRandom
= new ThreadLocal<Random>(() => new Random());
đây là mỗi luồng, vì vậy bạn không cần phải đồng bộ hóa.
new Random().Next((int)0xFFFF, (int)0xFFFFFF) % 256);
không mang lại bất kỳ số "ngẫu nhiên" nào tốt hơn.Next(0, 256)