我有一个在后台运行的服务,可以访问(读取和写入)sqlite数据库。相应的前台进程(主应用程序)也可以在我的android应用程序中访问(读取和写入)sqlite数据库。
如何防止与sqlite db同时访问/保存/读取相关的问题以及正确的方法是什么?
答案 0 :(得分:5)
有两种简单的方法可以做到这一点,第一种是ChirstopheCVB写道:创建一个同步方法。同步方法只能由一个线程访问,其他线程被阻止。
这是推荐的方法,因为它将所有与数据库访问相关的代码保存在一个地方。当您更改数据库的表格布局时,无需搜索所有代码并进行调整。你隐藏了#39;主线程中的详细信息。
如果要将db代码保留在主线程中,请使用信号量。在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看起来一样。
这有效,但有2个问题。首先,您正在阻止线程,因为您正在等待资源可用。存在风险,因为它可能永远不可用并且您已陷入僵局。
第二个问题更严重。想象一下,你有3个线程:A,B和C. C抓住锁,A& 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为您提供了信号量。一开始并不容易理解,但必须要理解你是否想要在不使用同步方法的情况下做你想要的事情(这样的方法可以为你做信号量而不需要额外的编码工作)。