4

特定の時点で複数のスレッドからアクセスできる/アクセスされる配列がある場合、それが非スレッドセーフになる正確な原因と、配列がほとんどの場合スレッドセーフであることを確認するために実行される手順は何ですか状況?

私はインターネットを広範囲に調べましたが、この件に関する情報はほとんどまたはまったく見つかりませんでした. )。誰かが私が最初に提示した質問に答えてくれるか、または誰かが上記の項目を説明する適切なドキュメントを指し示してくれることを本当に望んでいます.

編集: MSDN を調べたところ、ArrayList クラスが見つかりました。synchronize メソッドを使用すると、指定されたリストのスレッドセーフなラッパーが返されます。リストにデータを設定するとき (つまり、list1[someNumber] = anotherNumber;)、ラッパーは自動的にリストをロックしますか? それとも、まだロックする必要がありますか?

4

4 に答える 4

6

2 つのスレッドがまったく同じリソース (たとえば、ローカル コピーではなく、実際には同じリソースの同じコピー) にアクセスしている場合、多くのことが発生する可能性があります。最も明白なシナリオでは、スレッド #1 がリソースにアクセスしており、スレッド #2 が読み取りの途中でそれを変更した場合、予測できない動作が発生する可能性があります。整数のような単純なものでも、論理エラーが発生する可能性があるため、静的として宣言されたデータベース アクセス クラスなど、より複雑なものを不適切に使用した場合に生じる恐怖を想像してみてください。

この問題を処理する従来の方法は、機密性の高いリソースをロックして、一度に 1 つのスレッドだけが使用できるようにすることです。したがって、上記の例では、スレッド #1 はリソースへのロックを要求し、それを許可された後、読み取る必要があるものを読み取ります。スレッド #2 は読み取りの途中で来て、リソースへのロックを要求しますが、スレッド #1 がそれ​​を使用しているため、拒否され、待機するように指示されます。スレッド #1 が終了すると、ロックが解放され、スレッド #2 が続行できるようになります。

他にも状況はありますが、これは最も基本的な問題と解決策の 1 つを示しています。C# では、次のことができます。

1) フレームワークによってロック可能として管理される特定の .NET オブジェクトを使用します (Scorpion-Prince のSynchronizedCollection へのリンクなど) 。

2) [MethodImpl(MethodImplOptions.Synchronized)]を使用して、危険なことを行う特定のメソッドを一度に 1 つのスレッドだけが使用するように指示します。

3) lock ステートメントを使用して、潜在的に危険なことを行っている特定のコード行を分離します。

どのアプローチが最適かは、実際には状況次第です。

于 2012-06-08T16:23:02.877 に答える
4

特定の時点で複数のスレッドからアクセスできる/アクセスされる配列がある場合、それが非スレッドセーフになる正確な原因と、配列がほとんどの場合スレッドセーフであることを確認するために実行される手順は何ですか状況?

一般的に言えば、配列がスレッドセーフではないという事実は、配列へのアクセスを同期しないと、2 つ以上のスレッドが配列の内容を変更する可能性があるという概念です。

一般的に言えば、たとえば、スレッド 1 がこの作業を行っているとします。

for (int i = 0; i < array.Length; i++)
{
   array[i] = "Hello";
}

そして、この作業を行うスレッド 2 (同じ共有配列上)

for (int i = 0; i < array.Length; i++)
{
   array[i] = "Goodbye";
}

スレッドを同期させるものは何もないため、結果はどのスレッドが最初にレースに勝つかによって異なります。ランダムな順序で「こんにちは」または「さようなら」になる可能性がありますが、常に少なくとも「こんにちは」または「さようなら」になります。

文字列「Hello」または「Goodbye」の実際の書き込みは、CLR によってアトミックであることが保証されています。つまり、値「Hello」の書き込みは、「Goodbye」を書き込もうとしているスレッドによって中断されることはありません。いずれかが他方の前後に発生する必要があり、その間に発生することはありません。

そのため、アレイが互いに干渉しないように、ある種の同期メカニズムを作成する必要があります。lockこれは、C# のステートメントを使用して実現できます。

于 2012-06-08T16:14:04.033 に答える
2

C# 3.0 以降では、 SynchronizedCollectionと呼ばれるジェネリック コレクション クラスが提供されます。これは、「ジェネリック パラメーターで指定された型のオブジェクトを要素として含むスレッド セーフなコレクションを提供します」。

于 2012-06-08T15:55:39.893 に答える
0

配列は、同期メカニズムをサポートするための同期メソッドを定義するインターフェイスを実装するため、名前publicstaticキーワード (インスタントは保証されません)が指定されている場合、スレッド セーフです。System.ArrayICollection

ただし、配列の項目を列挙するコーディングは安全ではありません。開発者はlock、配列の列挙中に配列が変更されないようにステートメントを実装する必要があります。

元:

Array arrThreadSafe = new string[] {"We", "are", "safe"};
lock(arrThreadSafe.SyncRoot)
{
   foreach (string item in arrThreadSafe)
   {
     Console.WriteLine(item);
   }
}
于 2014-11-01T08:50:24.190 に答える