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 foreach
vò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 Array
lớ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 foreach
vòng lặp thay vì for
vò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 IEnumerable
mà 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 IEnumerable
sẽ là luồng an toàn.
foreach
hoạ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 for
vò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 foreach
chỉ có buôn bán IEnumerable/IEnumerator
là sai.
volatile
khô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.