sqliteデータベースにアクセス(読み取りおよび書き込み)できるバックグラウンドで実行されるサービスがあります。対応するフォアグラウンドプロセス(メインアプリ)は、Androidアプリケーションのsqliteデータベースにアクセス(読み取りおよび書き込み)することもできます。
sqlite dbへのアクセス/保存/読み取りを同時に行うことに関連する問題を防ぐにはどうすればよいですか?これを行う正しい方法は何ですか?
sqliteデータベースにアクセス(読み取りおよび書き込み)できるバックグラウンドで実行されるサービスがあります。対応するフォアグラウンドプロセス(メインアプリ)は、Androidアプリケーションのsqliteデータベースにアクセス(読み取りおよび書き込み)することもできます。
sqlite dbへのアクセス/保存/読み取りを同時に行うことに関連する問題を防ぐにはどうすればよいですか?これを行う正しい方法は何ですか?
これを行うには 2 つの簡単な方法があります。1 つ目は ChirstopheCVB が書いているとおりです。 同期されたメソッドを作成します。同期されたメソッドには 1 つのスレッドのみがアクセスでき、他のスレッドはブロックされます。
これは、DB アクセスに関連するすべてのコードを 1 か所に保持するため、推奨される方法です。データベースのテーブル レイアウトを変更する場合、すべてのコードを調べて調整する必要はありません。メインスレッドから詳細を「非表示」にします。
データベース コードをメイン スレッドに保持する場合は、セマフォを使用します。Java でのサポートがあります: http://developer.android.com/reference/java/util/concurrent/Semaphore.html
セマフォは、誰かが共有リソース (DB など) にアクセスしているかどうかを示す (簡略化された) 単一のオブジェクトです。DB にアクセスする前に、許可されているかどうかを確認し、許可されている場合は、他のユーザーをブロックするようにオブジェクトを設定します。他の人がリソースにアクセスできるように、オブジェクトをリセットしてください。
簡単な例として、スレッド A とスレッド B があり、グローバル変数 canUse があるとします。
Init: canUse = true;
Thread A:
while (!canUse) wait; // busy waiting, your thread is blocked
canUse = false; // canUse was true, now we grab access.
do our thing;
canUse = true; // Others are allowed to use the resource again.
スレッド B は同じように見えます。
これは機能しますが、2 つの問題があります。まず、リソースが利用可能になるのを待っているため、スレッドをブロックしています。利用できなくなり、デッドロックが発生する可能性があるため、リスクがあります。
2 番目の問題はより深刻です。A、B、C の 3 つのスレッドがあるとします。C がロックを取得し、A と B の両方が待機しています。以下が可能です
A: while (!canUse) wait;
B: while (!canUse) wait;
C: canUse = true;
A: Hooray, we can grab the resource
B: Hooray, we can grab the resource
A: canUse = false;
B: canUse = false;
上記の例は、変数のチェックと変更がアトミックな方法で行われることがいかに重要かを示しています。言い換えれば、他に何も起こり得ません。
幸いなことに、Java にはセマフォが用意されています。最初は理解するのは簡単ではありませんが、同期メソッドを使用せずに求めていることを実行したい場合は、理解する必要があります (そのようなメソッドは、余分なコーディング作業なしでセマフォとして機能します)。