私たちはオフィスで少し議論しましたが、文書化された答えはありませんでした。System.ArrayのSetValue/GetValueメソッドはスレッドセーフですか?
System.Array.SetValue
はスレッドセーフですか?
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 ??
}
}
}
ご覧のとおり、すべてのスレッドは、静的配列に異なる固有の項目を設定します。私はリフレクターを使ってコードを深く見ていました(そして、mscorlib.pdbを調べました)。最終的には
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private unsafe extern static void InternalSetValue(void * target, Object value);
への電話があります。これは文書化されていません。一般にSystem.Array
、特にSetValue(object, int)
へのMSDNのドキュメントを見てください。スレッドセーフについては何もありません。私は、配列の別の部分に、各スレッドが唯一の 作品ならば、 すべてがうまく
Iになると信じてい
:それはsimilar questionにジョンスキートの答えによって表現だとして
この問題に関しては
GetValue(int)
とSetValue(object, int)
に明確な回答を得ようとしています。誰かが文書のリンクを持っていますか、またはInternalSetValue
のより良い理解を持っていますか?
Eric Lippertが実際に意味する「スレッドセーフ」については、よくお読みください。http://blogs.msdn.com/ericlippert/archive/2009/10/19/what-is-this-thing-you-call -thread-safe.aspx –
あなたの例では、SetValueメソッドは呼び出されず、代わりにStelemオペコードがコールオペコードではなくコンパイラによって生成されます。 –