多线程访问数据库本身就存在分险,容易形成脏数据。幸好FMDB这个第三方库支持了多线程访问,从而解决了脏数据问题。然而也带来了死锁问题……
先看看FMDB的多线程机制的原理。
看了它的代码,发现其实很简单的一个思路,但是实现起来还真不容易,难怪花了好长时间才支持多线程!!它是生成一个请求队列,将一次事务进行封装放在队列中,只有一个事务完成了,才会进行下一个事务。这就出现了一种现象:如果某一个请求耗时过大,将会导致所有请求堵塞!!同时也要求:同一个线程中,在一个事务完成之前,不能进行下一个事务。
举个例子:
1 2 3 4 5 |
|
这个方法在执行sql成功后,将会调用increaseCounter方法:
1 2 3 4 5 |
|
而increaseCounter方法中又增加一个事务,去执行另外一个sql语句。
结果出现了这种现象:
第一个事务没结束,第二个事务等待第一个事务结束,而第一个事务等待第二个事务返回状态,出现死锁!!
正确的写法:
1 2 3 4 5 6 7 |
|
也就是将两个事务拆开。
总结:
- 多线程编程应该尽量采用事务队列
- 事务队列与Mysql等的锁数据库效果相似,即事务完成前,其他线程以及本线程不能访问数据库(注意不是锁表,是锁库)
- 一个事务内应该只包含数据库请求语句,不应当包含其他逻辑
- 一个请求不应耗时过长,否则出现线程等待