How to synchronize access to sqlite db between for

2019-03-31 01:16发布

问题:

I have a service that runs in the background which can access (read and write) to sqlite database. The corresponding foreground process (main app) can also access (read and write) to sqlite database in my android application.

How can i prevent problems related to trying to access / save / read at the same time to/from sqlite db and what should be the correct way to do this?

回答1:

There are 2 easy ways to do this, the first as ChirstopheCVB writes: Create a synchronized method. A synchronized method can only be accessed by one thread, other threads are blocked.

This is the recommended method, as it keeps all DB access related code in a single place. When you ever change the table layout of your database, you do not need to hunt through all of your code and make adjustments. You 'hide' the details from your main thread.

If you want to keep your db code in the main thread, then use semaphores. There is support for that in Java: http://developer.android.com/reference/java/util/concurrent/Semaphore.html

A semaphore is (simplified) a single object indicating if somebody is accessing a shared resource (e.g. your DB). Before accessing the DB, check if you are allowed and if you are, then set the object so it blocks others. Do your thing and reset the objects so others can try to access the resource.

A simple example, assume you have thread A & thread B, and a global variable 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.

Thread B looks the same.

This works, but there are 2 problems. First, you are blocking your thread because you are waiting for the resource to become available. There is a risk, because it might never become available and you have deadlock.

The second problem is more severe. Imagine you have 3 threads: A, B and C. C has grabbed the lock and both A & B are waiting. The following is possible

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;

Above example shows how important it is that checking the variable and changing it is done in an atomic way. In other words, nothing else can happen.

Fortunately, java provides you with semaphores. It is not easy to understand in the beginning, but a must to understand if you want to do what you are asking for without using synchronized methods (such methods act as semaphores for you without extra coding effort).