Dựa trên sự hiểu biết của tôi, được đưa ra một mảng C #, hành động lặp lại trên mảng đồng thời từ nhiều luồng là một hoạt động an toàn của luồng.
Bằng cách lặp qua mảng tôi có nghĩa là đọc tất cả các vị trí bên trong mảng bằng một vòng lặp cũ đơn giảnfor . Mỗi luồng chỉ đơn giản là đọc nội dung của một vị trí bộ nhớ bên trong mảng, không ai viết bất cứ điều gì vì vậy tất cả các luồng đều đọc cùng một thứ một cách nhất quán.
Đây là một đoạn mã làm những gì tôi đã viết ở trên:
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
for (int i = 0; i < Names.Length; i++)
{
temp.Add(Names[i].Length * 2);
}
return temp;
}
}
Vì vậy, sự hiểu biết của tôi là phương thức DoSomethingUseless này là luồng an toàn và không cần thay thế string[]bằng loại an toàn luồng ( ImmutableArray<string>ví dụ như).
Tôi có đúng không?
Bây giờ hãy giả sử rằng chúng ta có một ví dụ về IEnumerable<T>. Chúng ta không biết đối tượng cơ bản là gì, chúng ta chỉ biết rằng chúng ta có một đối tượng đang thực hiện IEnumerable<T>, vì vậy chúng ta có thể lặp lại nó bằng cách sử dụng foreachvòng lặp.
Dựa trên sự hiểu biết của tôi, trong kịch bản này, không có gì đảm bảo rằng việc lặp lại đối tượng này từ nhiều luồng đồng thời là một hoạt động an toàn của luồng. Nói cách khác, hoàn toàn có thể lặp lại qua IEnumerable<T>thể hiện từ các luồng khác nhau cùng một lúc sẽ phá vỡ trạng thái bên trong của đối tượng, để nó bị hỏng.
Tôi có đúng về điểm này không?
Vậy còn IEnumerable<T> thực hiện Arraylớp học thì sao? Nó có an toàn không?
Đặt một cách khác, chủ đề mã sau đây có an toàn không? (đây chính xác là mã giống như trên, nhưng bây giờ mảng được lặp lại bằng cách sử dụng foreachvòng lặp thay vì forvòng lặp)
public class UselessService
{
private static readonly string[] Names = new [] { "bob", "alice" };
public List<int> DoSomethingUseless()
{
var temp = new List<int>();
foreach (var name in Names)
{
temp.Add(name.Length * 2);
}
return temp;
}
}
Có bất kỳ tham chiếu nào nêu rõ các IEnumerable<T>triển khai trong thư viện lớp cơ sở .NET thực sự là luồng an toàn không?
Array) sẽ là luồng an toàn miễn là tất cả các luồng chỉ đọc nó. Tương tự với List<T>, và có lẽ mọi bộ sưu tập do Microsoft viết. Nhưng có thể làm cho riêng bạn IEnumerablemà không có chủ đề an toàn trong điều tra viên. Do đó, nó không đảm bảo rằng mọi thứ thực hiện IEnumerablesẽ là luồng an toàn.
foreachhoạt động với nhiều hơn chỉ là điều tra viên. Trình biên dịch đủ thông minh để biết rằng nếu nó có thông tin kiểu tĩnh chỉ ra rằng bộ sưu tập là một mảng, nó bỏ qua việc tạo ra liệt kê và chỉ truy cập trực tiếp vào mảng như nó là một forvòng lặp. Tương tự, nếu bộ sưu tập hỗ trợ triển khai tùy chỉnhGetEnumerator , thì việc thực hiện đó được sử dụng thay vì gọi IEnumerable.GetEnumerator. Quan niệm rằng foreachchỉ có buôn bán IEnumerable/IEnumeratorlà sai.
volatilekhông đảm bảo rằng bạn có được bản cập nhật mới nhất có thể cho một biến vì C # cho phép các luồng khác nhau quan sát các thứ tự đọc và ghi khác nhau, và do đó khái niệm "mới nhất" không được định nghĩa toàn cầu . Thay vì lý luận về sự mới mẻ, lý do về những hạn chế volatile về cách viết có thể được sắp xếp lại.