4

我有一个在后台运行的服务,它可以访问(读取和写入)sqlite 数据库。相应的前台进程(主应用程序)也可以访问(读取和写入)我的 android 应用程序中的 sqlite 数据库。

如何防止与尝试同时访问/保存/读取sqlite db相关的问题,正确的方法应该是什么?

4

1 回答 1

5

有两种简单的方法可以做到这一点,第一种是 ChirstopheCVB 所写的: 创建一个同步方法。一个同步方法只能被一个线程访问,其他线程被阻塞。

这是推荐的方法,因为它将所有与数据库访问相关的代码保存在一个地方。当您更改数据库的表布局时,您无需搜索所有代码并进行调整。您从主线程中“隐藏”详细信息。

如果要将数据库代码保留在主线程中,请使用信号量。在 Java 中有对此的支持:http: //developer.android.com/reference/java/util/concurrent/Semaphore.html

信号量是(简化的)单个对象,指示是否有人正在访问共享资源(例如您的数据库)。在访问数据库之前,请检查您是否被允许,如果允许,则设置对象以阻止其他对象。做你的事情并重置对象,以便其他人可以尝试访问该资源。

一个简单的例子,假设你有线程 A 和线程 B,以及一个全局变量可以使用。

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 看起来一样。

这可行,但有两个问题。首先,您正在阻塞线程,因为您正在等待资源可用。这是有风险的,因为它可能永远不会变得可用并且你会陷入僵局。

第二个问题更严重。假设您有 3 个线程:A、B 和 C。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;

上面的示例显示了检查变量并以原子方式进行更改的重要性。换句话说,没有其他事情会发生。

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).

于 2013-03-02T11:21:55.510 回答