我有一个在后台运行的服务,可以访问(读取和写入)sqlite 数据库。相应的前台进程(主应用程序)也可以访问(读写)我的android应用程序中的sqlite数据库。
如何防止与尝试同时访问/保存/读取 sqlite 数据库相关的问题,正确的方法应该是什么?
最佳答案
有两种简单的方法可以做到这一点,第一种方法如 ChirstopheCVB 所写:创建一个同步方法。一个同步方法只能被一个线程访问,其他线程被阻塞。
这是推荐的方法,因为它将所有与数据库访问相关的代码保存在一个地方。当您更改数据库的表布局时,您不需要搜索所有代码并进行调整。您从主线程中“隐藏”了详细信息。
如果您想将数据库代码保留在主线程中,请使用信号量。 Java 对此有支持: http://developer.android.com/reference/java/util/concurrent/Semaphore.html
信号量是(简化的)单个对象,指示是否有人正在访问共享资源(例如您的数据库)。在访问数据库之前,请检查您是否被允许,如果是,则设置对象以阻止其他人。执行您的操作并重置对象,以便其他人可以尝试访问该资源。
一个简单的例子,假设你有线程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 看起来一样。
这可行,但有两个问题。首先,您正在阻塞您的线程,因为您正在等待资源可用。这是有风险的,因为它可能永远不可用,而且你会遇到死锁。
第二个问题更严重。假设您有 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;
以上示例显示了以原子方式检查变量和更改变量的重要性。换句话说,不会发生任何其他事情。
幸运的是,java 为您提供了信号量。一开始并不容易理解,但如果您想在不使用同步方法的情况下执行您要求的操作(此类方法为您充当信号量而无需额外的编码工作),则必须理解。
关于android - 如何在前台和后台进程之间同步访问sqlite db?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15172715/