質問

再度同じ質問で申し訳ありませんが、確認させていただきたいと思います。

2 つのプロセス P1 と P2 があります。

P1はライター(プロデューサー)です。
P2 はリーダー (コンシューマ) です。

P1 が書き込む共有メモリまたはファイルがあり、P1 が書き込むとすぐに、P2 に読み取りの通知が送信される必要があります。

私の理解によれば、P1の疑似コードは次のようになります。

Open shared file
Create a named event("Writedone") to signal write for P2 process
Do some processing on file
Mutex.Lock()
Write to File
Mutex.Unlock()
Signal named Event.
CloseHandle on file

現在P2中

Open handle to Shared file
Open handle to named event
WaitForSingleEvent on named event("Writedone")
Read from file
CloseHandle on file

質問:

  1. リーダーにロックが必要ですか?リーダーはファイルを読み取るだけで、変更しません。したがって、リーダーにはロックは必要ないと思います。考えは?ロックがないと場合によっては問題が発生する可能性がありますか?
  2. 読み取りと書き込み中に毎回ファイルへのハンドルを開いたり閉じたりしています。それは必要ないと思います。コンストラクターでファイルハンドルを開いて、リーダーとライターのデストラクターでファイルハンドルを閉じることができます。しかし、ファイルを書き込みで使用しているときに、ファイルから読み取ることはできますか?

編集:ライターがファイルの最後に 10 バイトを書き込むたびに、リーダーはライターによって書き込まれた最新の 10 バイトを読み取ることになります。

役に立ちましたか?

解決

答えは次のとおりです。ロックは、両方のスレッドが同じ共有リソースを同時に使用できる場合 (その場合に限り) 必要です。特定の実装に関する十分な情報がありませんが、いくつかコメントがあります。

  1. 書き込み中のみロックするのは意味がありません。多少のオーバーヘッドが追加されるだけですが、リーダーも正しくロックされるまで同時アクセスは妨げられません。
  2. ファイルの記述子に関連付けられた構造を変更するファイル操作がまったく同期されていない場合は、ロックが必要になります。P2 がまだ読み取り中に、P1 がファイルへの書き込みを開始する可能性があります。基礎となる同期を行わずに読み取りおよび書き込み操作で同じシステム構造を変更すると、データが破損することになります。どの特定の関数 (ライブラリ) を使用したかについて言及していないため、これが当てはまるかどうかを判断するのは困難です。ファイル操作はほとんどのシステムで同期されるため、問題にはなりません。
  3. 「情報の 10 バイト部分」について書いたことから、明示的なロックは (#2 が強制しない限り) 必要ないようです。P1 は量子データを生成します。データを読み取る準備ができると、P1 はそのことを (イベントによって) P2 に通知します。いずれにしても、イベントの受け渡しは内部的に同期する必要があります)。P2 は、量子データを読み取ることができることを認識しているため、後続の通知を待つ必要があります。前の通知が処理される前に、後続の通知が送信される場合があります。したがって、何らかの方法でイベントをキューに入れる必要があります。イベント通知の代わりにセマフォを使用することもできます。

他のヒント

あなたはロックを取得するリーダーが必要です - イベントの使用が代わるものではありません。それがなければ、作家は、読者のコード内の任意の時点で書き込みを始めることができます。

あなたは絶対に読者が読むことができる前に、ファイルへの追加からプロデューサーを防ぐためにロックする消費者を必要としています。このシナリオを想像します:

Producer writes and signals
Consumer receives signal
Consumer opens the file
Producer fires again and writes another 10 bytes
Producer signals
Consumer reads the last 10 bytes
Consumer closes the file
あなたの名前のイベントがリセットまたはオートリセット、手動の場合は、

次に何が起こるかに依存します。それはオートリセットだ場合、消費者は、第二の信号が表示され、戻って、もう一度同じことをお読みください。それはマニュアルリセットだ場合、消費者は、イベントをリセットし、プロデューサーが書いた最後のものを欠場する予定です。

プロデューサーが十分に迅速に対応することができた場合でも、ロックを使用すると、競合状態を持っていることに注意してください。これは、消費者が最初に読み取ることができる前に、プロデューサーがファイルに第二のレコードを入れることができるかもしれない、です。

あなたがここに持っていることはファイルに実装FIFOキューであることが表示されます、そして、あなたはより速くプロデューサーがそれを作成することができますよりも、データを処理するために、消費者の能力に依存しています。あなたがの保証のその行動できるなら、あなたは大丈夫です。そうでなければ消費者は、それが次の読むべきところ、それは知っているように、それが最後に読んでどこを追跡する必要があります。

  1. ライターがいつでも書き込みを開始できる場合は、リーダーのミューテックスをロックする必要があります。P2 が開くことができるように、ミューテックスが名前付きであることを確認してください。

  2. 両方のプロセスで FileShare.ReadWrite を使用してファイルを開く場合は、開いたままにすることができます。

リーダーでは、再度読み取る前に、EOF に達した場所までシークする必要がある場合があります。

ライターが常に追加していることが確実で、レコードがどこで終わるかがわかり (たとえば、レコードが常に 10 バイトであるため)、多少の遅延を許容でき、ライターが常に完全なレコードを書き込む場合は、ミューテックスなしでこれを行うことができます。そしてイベント全般。FileShare.ReadWrite でファイルを開き、リーダーで同じ場所を探し続けてレコードを読み取ろうとし、できなかった場合は少しの間スリープします。レコード全体を読み取ることができた場合は、レコードを 1 つ取得したことになります。自分の位置を把握し、ループバックしてその場所まで探し、再度読み取りを試みます。これは、Unix での tail -f の動作のようなものです。

は別に、通常の同期機能から、あなたはを使用することができますWindows上のファイル変更通知のAPIは、ファイルの変更を待つます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top