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, Nextsẽ thay đổi trạng thái nội bộ của Randomthể 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 Randomnà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
Randomtrườ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)