ContentProvider相关_沙漠一只雕得儿得儿的博客-CSDN博客_contentprovider线程安全
1、如果是单进程多线程,多线程访问数据库的时候会出现这样的异常,Sqlite 自身是不支持多线程同时操作的
- java.lang.IllegalStateException: Cannot perform this operation because the connection pool has been closed .
-
- 或 java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase : 或 java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase:
很简单,直接用多线程锁就可以
2、如果是多进程呢:sqlite多进程多连接经常死锁。设计上就不是干这事的。
SQLite的并发性允许多个进程一次打开数据库文件,并允许多个进程一次读取数据库。当任何进程想要写入时,它必须在更新期间锁定整个数据库文件。但这通常只需要几毫秒。其他流程只是等待作者完成然后继续他们的业务。其他嵌入式SQL数据库引擎通常只允许单个进程一次连接到数据库。
多进程写sqlite的实验:sqlite3的进程安全访问测试_LostSpeed的博客-CSDN博客
sqlite3同一个表无法由2个进程同时读写表记录。
总有一个进程会出现“database is locked”的报错,去查了资料。大概意思是:因为是文件型数据库,无法使2个进程同时向同一个文件写数据。我的应用是一个读(读完一条记录删一条),一个写,应该会触发sqlite的文件读写锁吧。
尝试sql执行失败后重试,倒是可以继续跑。但是每一个SQL都有可能失败,都要重试。这执行效率就下来了。
3、多线程同时往数据库插入数据
现在我们有Thread 1和Thread 2两个线程要往数据库中插入数据:
那么我们可能会收到下如下错误logcat,并且其中一个线程的插入写数据库操作将会执行失败:
android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
为什么会发生 SQLiteDatabaseLockedException 异常呢?
因为每一次我们新创建new一个SQLiteOpenHelper对象,都会新建立一个数据库连接database connection。如果同时用两个不同的connection往数据库中写数据,其中一个将会失败,并收到database is locked异常。
如何确保多线程先使用的是同一个数据库连接database connection?
使用单例类。
SQLite 与线程
SQLite 是线程安全的。
线程模型
SQLite 支持如下三种线程模型
设置线程模型
SQLite 可以通过以下三种方式进行线程模型的设置,在实际应用中选择任一一项都可以。
SQLite 并发和事务
事务
事务是 SQLite 的核心概念。对数据库的操作 (绝大部分) 会被打包成一个事务进行提交,需要注意的是,这里的打包成事务是自动开启的。举例而言,如果简单在一个 for 循环语句里向数据库中插入 10 条数据,意味着将自动生成 10 个事务。但需要注意的是事务是非常耗时的,一般而言, SQLite 每秒能够轻松支持 50000 条的数据插入,但是每秒仅能够支持几十个事务。一般而言,事务速度受限于磁盘速度。所以在批量插入时需要考虑禁用自动提交,将其用 BEGIN ... COMMIT 打包成一个事务。
锁和并发
SQLite 通过五种锁状态来完成事务。
一个线程只有拥有低级别锁时才能够获得更高一级的锁