1 つのアプリケーションの 3 つのスレッドが DLL から静的メソッドを (ほぼ) 同時に呼び出すとどうなるか知りたいと思っていました。各スレッドに DLL の 3 つのインスタンスがロードされていますか?それとも、最初のスレッドが DLL 静的メソッドで完了した後、他のスレッドは DLL にアクセスするだけですか?
3 に答える
ロードされた DLL のインスタンスが 3 つ (スレッドごとに 1 つ) ありますか?
いいえ。通常、 DLL はプロセスごとに 1 回読み込まれます。(ここにはいくつかの微妙な問題があります。 and を使用すると、同じアセンブリが 2 回読み込まれる可能性がLoad
ありLoadFrom
ます。ただし、これはまれなケースであり、スレッド化とは関係ありません。)
2 番目と 3 番目のスレッドは、最初のスレッドが DLL 静的メソッドを使用して完了した後にのみ DLL にアクセスできますか?
いいえ; 静的メソッドは自動的にシリアル化されません。一度に 1 つのスレッドのみがアクセスするようにするメソッドが必要な場合は、それを行うためのコードを自分で作成する必要があります。
ただし、静的コンストラクターはそのように動作します。ランタイムは、「レースに勝つ」スレッドが静的コンストラクターを実行することを保証します。他のスレッドは、最初のスレッドが cctor を完了するまで待機します。詳細については、それに関する私の最近の一連の記事を読んでください。
一般に、非静的オブジェクトの場合でも、コードは1回ロードされます。
コードではなく、宣言された変数(まとめてstateと呼ばれる)に含まれている情報であり、心配する必要があります。
DLL は一度だけメモリにロードされます。
同じプロセス内に複数のスレッドが呼び出しを行ったり、DLL 内のグローバルにアクセスしたりする場合、DLL はクリティカル セクションを使用してグローバル/共有データへのアクセスを保護することにより、スレッドの安全性を保証する必要があります。
DLL にアクセスする複数のプロセスから複数のスレッドが存在する場合、同じ DLL にアクセスするプロセスから複数のスレッドが存在しない限り、スレッド セーフは問題になりません。
オペレーティング システムはメモリを巧みに管理し、最初はコード セクションとデータ セクションの 1 つのコピーだけで開始します。データ セクション ページは読み取り専用でマップされます。いずれかのプロセスでグローバル データを変更する必要がある場合、OS はセグメンテーション フォールトを取得し、ページのコピーを作成して、プロセスのメモリ空間に書き込み可能としてマップします。このアプローチは、コピーオンライトと呼ばれます。