【问题标题】:Android -- SQLite + SharedPreferences, 2 Threads Simultaneous Read/Write?Android -- SQLite + SharedPreferences,2个线程同时读/写?
【发布时间】:2010-07-13 01:06:14
【问题描述】:

我有一个程序的两个部分(实际应用程序和一个 BroadcastReceiver),它们可能会尝试连接和修改 SQLite 数据库和 SharedPreferences 文件。

1) 我知道您可以与单个 SQLite 数据库建立多个连接。我还读到 SQLite 在尝试修改或读取数据库(UPDATE、INSERT 等)时可以“锁定”数据库,所以我如何正确处理 2 个线程尝试修改/读取单个 SQLite 数据库的情况同一时间?

现在,我的数据库连接代码/类中有这个代码 sn-p:

private SQLiteDatabase myDatabase;
public boolean insert(ContentValues columnValueMap) throws Exception
    {
        long result = 0;
        int attempt =0;
        do
        {
            if(!myDatabase.isDbLockedByOtherThreads() && !myDatabase.isDbLockedByCurrentThread())
            {
                synchronized (myDatabase)
                {
                    result=myDatabase.insertOrThrow(TABLE_NAME, TEXT, columnValueMap);
                    if(result ==0 || result == -1)
                    {
                        return false;
                    }
                    return true;
                }
            }
            else
            {
                Thread.sleep(50);
            }
            attempt++;
        }while(attempt<=5);

        throw new Exception("Database Locked!");
    }

2) 我是否还需要担心同时访问 SharedPreferences 文件(哪个线程先获得访问权限并不重要,我只是担心会引发错误)?

谢谢。

[编辑]建议的更改

public boolean insert(ContentValues columnValueMap) throws Exception
    {
        long result = 0;
        synchronized (myDatabase)
        {
            result=myDatabase.insertOrThrow(TABLE_NAME, SMS_TEXT, columnValueMap);

            if(result ==0 || result == -1)
            {
                return false;
            }
            return true;
        }
    }

【问题讨论】:

    标签: java android multithreading sqlite sharedpreferences


    【解决方案1】:

    首先,数据库已经内置了锁定支持,并且默认开启。如果您想安全,请致电SQLiteOpenDatabase.setLockingEnabled(true)

    至于对共享首选项的访问,我会将所有对 SharedPreferences 的访问(读取和写入)封装在所有使用同步的小函数中。 (确保它们是原子的)。

    【讨论】:

    • 感谢您的回复。那么,我不应该担心 SQLite 的多个线程吗?例如,如果两个线程都在编辑数据库,线程 1 将等待线程 2 完成,因为文件锁定是内置的?如果是这样,为什么存在方法“isDbLockedByOtherThreads()”和“isDbLockedByCurrentThread()”?至于 SharedPreferences,我会根据您的建议将同步添加到该代码段。谢谢。
    • 从文档中,setLockingEnabled() 用于“通过在关键部分周围使用锁来控制 SQLiteDatabase 是否是线程安全的。”。这意味着操作系统会为您做所有事情。 (顺便说一句,一般来说,我永远不会像你上面那样轮询锁 - 如果你真的必须自己同步某些东西,只需创建一个对象并对其使用通知/等待。轮询通常是悲伤的保证。自旋锁应该永远在少数有意义的情况下使用。
    • 好的,有道理。我已经看到了在同步块中将虚拟对象用作监视器的示例,但是我需要在这里这样做吗?我在上面的编辑中提出的更改是更好的方法吗?谢谢。
    • synchronized(myDatabase) 已经锁定了数据库对象,所以你不需要做任何进一步的同步。这假设您只有一个数据库对象。如果没有,请创建一个虚拟锁对象并改用它。同步(lockObject){everyInHereIsAtomic; }。但是,如果设置了 setLockingEnabled() ,则在 SQLiteDatabase 的特定情况下您根本不需要做任何事情(我想您的示例现在指的是 SharedPreferences 对象)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-27
    • 2014-07-15
    • 2018-11-24
    • 1970-01-01
    • 2018-11-14
    • 1970-01-01
    • 2021-06-24
    相关资源
    最近更新 更多