15

2 つの異なるスレッドから同じディレクトリを安全に作成しようとしても、そのうちの 1 つが例外をスローしたり、他の問題に遭遇したりすることはありませんか?

MSDNによると、既に存在するディレクトリを呼び出しても問題ないことに注意してくださいCreateDirectory()。この場合、メソッドは何もしないと予想されます。

4

3 に答える 3

17

呼び出し自体は、Directory.CreateDirectory複数のスレッドから安全に行うことができます。そうしても、プログラムまたはファイル システムの状態が破損することはありません。

Directory.CreateDirectoryただし、例外がスローされないことを保証するような方法で呼び出すことはできません。ファイル システムは、制御できない他のプログラムによっていつでも変更される可能性がある、予測不可能な獣です。たとえば、次のことが発生する可能性が非常に高い

  • プログラム 1 スレッド 1: を呼び出しCreateDirectoryc:\temp\foo成功する
  • プログラム 2 スレッド 1:c:\tempプログラム 1 ユーザーからのアクセスを削除します
  • プログラム 1 スレッド 2:CreateDirectoryアクセス不足による呼び出しとスロー

要するにDirectory.CreateDirectory、ファイルシステム、または実際にはファイルシステムに触れるすべての関数が、それに応じてスローおよび処理できると想定する必要があります。

于 2012-03-05T19:36:58.920 に答える
6

DirectoryのMSDN ドキュメントから:

この型の public static (Visual Basic では共有) メンバーはすべて、スレッド セーフです。インスタンス メンバーは、スレッド セーフであるとは限りません。

したがって、CreateDirectory は静的であるため、はい、スレッド セーフです。

つまり、@JaredPar が指摘しているように、メソッドが例外をスローできる理由は、スレッド セーフの問題だけではありません。ファイルシステム呼び出しが (マルチスレッドかどうかに関係なく) 例外をスローする理由は多数あり、それらを考慮する必要があります。

それがスレッド セーフであるということで、私 (および MSDN) はそれを文字通りに解釈しているだけであり、「このメソッドは、無効な状態、競合状態、または一般的に安全でないことに関連するその他の悪影響を引き起こす可能性のある方法で、共有プログラムの状態を変更しない」という意味です。マルチスレッドコード」

于 2012-03-05T19:36:10.247 に答える
4

@JaredParの答えを詳しく説明するには、競合状態が発生しています。最初の呼び出しでフォルダが完全に作成されてから 2 番目の呼び出しが開始される場合、すべて問題ありません。

ただし、最初の呼び出しがまだ処理されている間に 2 番目の呼び出しが OS に到達すると、OS はロックの問題のために 2 番目の呼び出しに失敗する可能性があり、例外が発生します。

予測できないフォルダーが作成されない、またはフォルダーがまったく作成されないという意味で、スレッドセーフです。

詳しく説明すると、同じフォルダーが同時に 2 回作成されたときに Windows に内部競合状態がないことを 100% 確信しているわけではありませんが、それによってディスクを破棄できないことは確かです。両方の作品が立ち往生してデッドロックになります。そのうちの 1 つが成功し、もう 1 つが失敗しますが、フォルダーは作成されます。

したがって、確実に確認するために、ヒューリスティックは次のようになります。

  • ディレクトリの作成
  • 失敗した場合は、ランダムな時間 (たとえば、0.2 ~ 0.5 秒) 待ってから再試行します。
  • 常に失敗する場合 (たとえば、3 回連続して失敗する場合)、別の問題が発生している可能性があります。フォルダーへのアクセス許可がない、ディスクがいっぱいであるなどです。

    ちなみに、アプリ起動時に一度フォルダを作成してみてはいかがでしょうか。

于 2012-03-05T19:53:08.990 に答える