2009-05-20 8 views
3

私が書いているアプリケーションでは、多くの基本型を書く必要がありますが、これはおそらく不変です。しかし、私はどのように変更可能な型を並列アプリケーションで不変のものと比較するのか不思議です。変更不可能な並列アプリケーションの場合

可変オブジェクトのロックを使用できますか?パラレルアプリケーションで不変型で使用される他のテクニックとはどのように比較されますか?

少なくとも、不変型のロックを使用することはできませんか?

答えて

7

種類

できるだけ多く
  • 利用不変タイプ。
  • 可能な限り明示的なロックの代わりにスレッドセーフなコレクションを使用します。
  • 他に妥当な選択肢がない場合は、変更可能なタイプのみを使用してください。できるだけ多くの

スレッド

  • 使用スレッドプール。
  • スレッドプールが不可能な場合は無限ループを使用してください。
  • 最後の手段としてスレッドを手動で開始および停止します。

明示的なロックを使用する必要がある場合は、完全に文書化してください。特に、オブジェクトをロックする順序になるとき。 Fooオブジェクトが常にBarオブジェクトの前にロックされ、Foo(key 100)がFoo(key = 200)より前に常にロックされていることがわかっている場合、デッドロックは発生しません。

+2

をそして、あなたは.NET 4.0にしている場合は、タスク並列ライブラリを使用することを検討してください。 –

+0

まだスレッドプールですが、はるかにスマートなものです。私は、.NETのThreadPoolクラスがそれに賛成で反対していると聞いています。 –

3

並列化可能なアプリケーションを書くための鍵は、変更可能な共有状態を避けることです。スレッド間で可変状態を共有するには、通常は何らかの形のロックを必要とする同期が必要です。不変型を使用すると、それらのオブジェクトの状態を変更できないようにして、誤って状態を共有しないようにすることができます。しかし、これは魔法の弾丸ではなく、単に設計の選択肢です。並列化しようとしているアルゴリズムに共有状態が必要な場合は、何らかの同期を作成する必要があります。

ロック機能には影響はありません。

1

変更可能な型を使用すると、Write-After-ReadエラーまたはWrite-After-Writeエラーに自分自身をさらすことになります。これらは、値の更新に関連する同期エラーで、他のスレッドが同時に値を読み込んだり更新したりしています。

同期エラーを防止するには、何らかのロック機構を使用する必要があります。明示的なロックを使用する場合は、ロックを取得する順序に非常に注意する必要があります。注意しないと、デッドロックが発生する可能性があります。たとえば、スレッドAがロックXを取得した後、スレッドBがロックYを取得します。後でスレッドAがロックYを要求し、スレッドBがロックXを要求します。これにより、スレッドは決して解放されないロックを無期限に待機します。ロックするための親指の

つ良いルール:特定の順序で

  • 獲得ロックは、できるだけ短時間
  • ホールドロック(例えば、常にロックY前にロックXを取得します)。あなたがそれらを必要とするときにそれらを取得し、あなたがすぐにそれをリリースします。

作成後にオブジェクトに書き込むことがない場合は、オブジェクトにアクセスする前にロックする必要はありません。したがって、不変オブジェクトをロックする必要はありません。

0

可能な場合は、不変型を使用してください。あなたが(シリアライゼーションなど)する必要があるときは、変更可能な型を使用してください。

すべての並列化にSystem.Threading.Tasksを使用する - タスクは、asyncとキーワードが追加されるときにC#5の言語でビルドされます。

私はC#で可変/不変の種類についての記事を書いた:http://rickyhelgesson.wordpress.com/2012/07/17/mutable-or-immutable-in-a-parallel-world/

関連する問題