Chúng tôi đã có một cuộc thảo luận nhỏ trong văn phòng và không có câu trả lời nào được ghi lại:Phương thức SetValue/GetValue của System.Array có an toàn không?
Có phải an toàn là System.Array.SetValue
chủ đề an toàn không?
using System;
using System.Text;
using System.Threading;
namespace MyApp
{
class Program
{
private static readonly object[] arr = new object[3];
static void Main(string[] args)
{
string value1 = "hello";
int value2 = 123;
StringBuilder value3 = new StringBuilder();
value3.Append("this");
value3.Append(" is ");
value3.Append("from the StringBuilder");
var states = new object[]
{
new object[] {0, value1},
new object[] {1, value2},
new object[] {2, value3}
};
ThreadPool.QueueUserWorkItem(MySetValue, states[0]);
ThreadPool.QueueUserWorkItem(MySetValue, states[1]);
ThreadPool.QueueUserWorkItem(MySetValue, states[2]);
Thread.Sleep(0);
Console.WriteLine("press enter to continue");
Console.ReadLine();
// print the result
Console.WriteLine("result:");
for (int i = 0; i < arr.Length; i++)
{
Console.WriteLine("arr[{0}] = {1}", i, arr[i]);
}
// quit
Console.WriteLine("press enter to quit");
Console.ReadLine();
}
// callback
private static void MySetValue(object state)
{
var args = (object[]) state;
var index = (int)args[0];
var value = args[1];
arr[index] = value; // THREAD-SAFE ??
}
}
}
Như bạn có thể thấy, mỗi chuỗi đều đặt mục khác nhau, duy nhất trong mảng tĩnh. Tôi nhìn sâu vào mã bằng cách sử dụng phản xạ (và nhìn vào mscorlib.pdb). Cuối cùng, có một cuộc gọi đến:
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private unsafe extern static void InternalSetValue(void * target, Object value);
Tài liệu nào không được ghi lại. Hãy xem tài liệu MSDN của System.Array
nói chung, và để SetValue(object, int)
đặc biệt .. Không có gì về an toàn thread (hoặc có thể tôi thiếu một cái gì đó).
Như nó thể hiện qua câu trả lời của Jon Skeet đến một similar question:
Tôi tin rằng nếu mỗi thread chỉ công trình trên một phần riêng biệt của mảng, tất cả sẽ tốt
tôi đang cố gắng nhận được câu trả lời rõ ràng cho GetValue(int)
và SetValue(object, int)
về vấn đề này. Có ai đó có liên kết tài liệu và/hoặc hiểu rõ hơn về InternalSetValue
không?
Đọc tốt về những gì "an toàn chủ đề" thực sự có nghĩa là bởi Eric Lippert: http://blogs.msdn.com/ericlippert/archive/2009/10/19/what-is-this-thing-you-call -read-safe.aspx –
Trong ví dụ của bạn, phương thức SetValue sẽ không được gọi, thay vào đó một mã opel Stelem sẽ được trình biên dịch phát ra, và không phải là một mã opcode gọi. –