2008-09-15 14 views
3

私は大量のデータをインポート(コアデータ)中にGUIを応答し続けるために、ココアソフトウェアに取り組んでいます。私はメインスレッドの外でインポートを実行する必要があります。スレッドを作成したスレッドで明示的にアクセスしないと、スレッド外で作成したオブジェクトを操作するのは安全ですか?

ロックを使用せずにメインスレッドで作成したオブジェクトにアクセスすることは安全ですかスレッドが実行されている間は明示的にオブジェクトにアクセスしません。

答えて

4

コアデータでは、同じコーディネータと永続ストアに接続されたインポートスレッド用の別個のマネージオブジェクトコンテキストが必要です。メインスレッドで使用されているコンテキストで作成されたオブジェクトを別のスレッドに投げ込んで、動作させることはできません。さらに、これのために独自のロックを行うことはできません。必要に応じて、オブジェクトが管理対象オブジェクトのコンテキストをロックしている必要があります。しかし、それらのオブジェクトがあなたのビューによってコントロールにバインドされている場合、コンテキストのロックを追加できる「フック」はありません。

無料のランチはありません。

Ben Trumbullは別のコンテキストを使用する必要がある理由と、単に「読んでいるだけで」と思うほど簡単ではないと考えられる理由を説明しています(this great post from late 2004 on the webobjects-dev list)。 (スレッド全体は素晴らしいです)彼はEnterprise Objects FrameworkとWebObjectsについて議論していますが、彼のアドバイスはCore Dataにも完全に適用されます。彼のメッセージの肉で "EC"を "NSManagedObjectContext"と "EOF"を "Core Data"に置き換えてください。

以前のEnterprise Objects Frameworkのように、コアデータ内のスレッド間でデータを共有する問題の解決策は「しない」です。実際に正直言ってスレッド間でデータを共有する必要がある場合は、独立したオブジェクトグラフをスレッド分離コンテキストで保持し、1つのコンテキストから保存通知の情報を使用して他のコンテキスト再フェッチするもの-[NSManagedObjectContext refreshObject:mergeChanges:]は、この使用をサポートするように特別に設計されています。

+0

これを見ている人にとって、時代は変わりましたが、Core Dataの並行性は依然としてスレッド閉じ込めの中心にあります。詳細については、OS X 10.7およびiOS 5.0のコアデータリリースノート(http://developer.apple.com/library/mac/#releasenotes/DataManagement/RN-CoreData/_index.html)を参照してください。この質問の文脈における最も刺激的な変更は、新しいブロックベースの並行性APIと並行性と分離のためのネストNSManagedObjectContextです。 –

0

ロックを使用するポイントは、2つのスレッドが同じリソースにアクセスしようとしないようにすることです。あなたが他の何らかの仕組みでそれを保証できるなら、それを求めてください。

0

安全であっても、スレッド間で共有データを使用することは、これらのフィールドへのアクセスを同期させずに行うことをお勧めします。どのスレッドがオブジェクトを作成したかは関係ありませんが、複数の実行行(スレッド/プロセス)が同時にオブジェクトにアクセスしている場合は、データの不一致が発生する可能性があるためです。

アクセスを同期させない方が安全だと確信している場合は、1つのスレッドだけがこのオブジェクトにアクセスすることを絶対に確信している場合。それでも、アプリケーションの変更によって同じデータを共有する2番目のスレッドがアクセスを同期することを心配せずに済むまで待つのではなく、今度は自分のコードに同期を入れたいと思います。

0

はい、安全です。かなり一般的なパターンは、オブジェクトを作成し、それをキューまたは他のコレクションに追加することです。 2番目の「コンシューマ」スレッドは、キューからアイテムを取り出し、それらを使って何かを行います。ここでは、キューを同期する必要がありますが、キューに追加されたオブジェクトは同期しないでください。

すべてを同期させて、最高のものを期待するのは良い考えではありません。あなたのデザインと、あなたのオブジェクトに作用するスレッドについて正確に考える必要があります。

0

あなたがそれを行うことができますはい二プログラマが来ると、あなたが作った同じ仮定を理解していないまで、それは

... 安全になります。その2番目(または3番目、4番目、5番目、...)のプログラマは、(クリエイタースレッドの)安全でない方法でオブジェクトを使用し始める可能性が高いです。引き起こされた問題は非常に微妙であり、追跡するのが難しいかもしれません。その理由だけで、このオブジェクトを複数のスレッドで使用したいので、オブジェクトのスレッドを安全にします。

私はプログラム的にスレッドの問題を回避するためのスキームを考案意味「スレッドセーフ」とは:(コメントを残した人たちのおかげで)、明確にするために

。私は必ずあなたのオブジェクトの周りのロッキングスキームを考案することを意味しません。あなたは、作成者のスレッドでオブジェクトを使用することを違法(または非常に困難)にする方法をあなたの言語で見つけることができます。たとえば、作成者のスレッドでスコープをオブジェクトを作成するコードのブロックに限定します。作成したら、オブジェクトをユーザースレッドに渡して、作成者スレッドに参照がないことを確認します。

例えば、C++でのあなたの作成したスレッドで次に

void CreateObject() 
{ 
    Object* sharedObj = new Object(); 
    PassObjectToUsingThread(sharedObj); // this function would be system dependent 
} 

、あなたは、もはやその作成後のオブジェクトへのアクセスを持っていない、責任は使用してスレッドに渡されます。考慮すべき

+0

ほとんどの言語には、並行プログラミングに役立つ言語レベルのツールは多数ありません。私たちはドキュメントと開発者のコ​​ミュニケーションに悩まされています。私はまだオブジェクトのスレッドセーフを「ちょうど良い」ものにするのは悪い考えだと考えていますが、おそらくオブジェクトを不変にすることが最良の選択です。 –

+1

一般に、「オブジェクトをスレッドセーフにする」ことはできません。オブジェクトは通常、オブジェクトの大きなグラフの一部であり、通常はグラフ全体がトランザクションのセマンティクスを必要とします。そのため、我々は、オブジェクトではなくコンテキスト上でロックすることで、我々がやったやり方でCore Dataを設計したのです。 –

+0

C++の例は誤解を招きます。 alloc/initを使用してNSObjectインスタンスを作成して、この例のように処理することはできますが、NSManagedObjectはそのインスタンスで同じことができるとは保証しません。 –

0

2つのことは、以下のとおりです。

  • あなたはそれが他のスレッドに利用可能になる前に、オブジェクトが完全に作成され、初期化されることを保証することができなければなりません。
  • メイン(GUI)スレッドがデータがロードされ、すべてが正常であることを検出するメカニズムが必要です。スレッドセーフであるためには、必然的に何らかのロックが必要になります。
1

私は、これはCoreData NSManagedObjectContextによって管理されているNSManagedObjects(またはサブクラス)を行うことは安全ないであると信じています。一般的に、CoreDataは、管理対象オブジェクトの状態で、個別のスレッド内のオブジェクトに関連する障害を発生させるなど、多くのトリッキーなことを行う可能性があります。特に、[NSManagedObject initWithEntity:insertIntoManagedObjectContext:](OS X 10.5以降のNSManagedObjectの指定された初期化子)は、返されたオブジェクトが他のスレッドに渡されることを保証するものではありません。

複数のスレッドでCoreDataを使用することについては、Appleのdev siteに詳しく記載されています。

関連する問題