fmdb中databasequeue的使用,避免死鎖
在ios開發中,大家很可能會用到這樣一個資料庫封裝:fmdb.
該封裝相比coredata來說有他自己的優勢:介面清晰,設計簡單,符合規範,多執行緒情況下使用databasequeue來進行操作也很方便,還可以在其基礎上再進行一些封裝來方便專案的使用。
正是因為fmdb的簡單性,所以很容易被誤用。在我們的專案開發中就遇到了一例(我們專案中的程式碼進行了封裝,我這裡將其還原,寫示例來作說明):
- [queue inTransaction:^(FMDatabase *db, BOOL *rollback) {
- [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];
- [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];
- [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];
- [
queue
inDatabase:^(FMDatabase *db) {
// do work B
}]; - if (whoopsSomethingWrongHappened) {
- *rollback = YES; return;
- }
- // etc…
- [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];
- }];
注意第6行往下,是不是混入了什麼奇怪的東西?
從這裡看起來問題非常明顯了,但實際專案中介面被進行了一些封裝,所以很難一眼看出問題,這裡的問題是這樣的:
在queue的事務內部又巢狀使用了該queue去執行任務b,而作為一個序列化的佇列來說必須要等該事務整個執行完畢才能執行任務b;此時任務b無法走下去,該事務也就無法執行完畢,導致了死鎖。
用一個比喻來說這個問題:一個人出門把門鎖上了,然後把鑰匙從門縫又塞回到家裡,這樣他就無法再進入家門了。
這個誤用其實很低階,而且從原理上講任何序列佇列裡面序列任務巢狀執行都有問題。
另外,fmdb的官方文件也多次提醒避免巢狀使用,請大家寫程式碼的時候一定要注意~
相關文章
- 面試:什麼是死鎖,如何避免或解決死鎖;MySQL中的死鎖現象,MySQL死鎖如何解決面試MySql
- java如何避免程式死鎖Java
- [Java併發]避免死鎖Java
- 面試官:什麼是死鎖?怎麼排查死鎖?怎麼避免死鎖?面試
- 作業系統(5) 死鎖的概念 死鎖產生的必要條件 死鎖的處理策略 預防死鎖 避免死鎖 死鎖的檢測和解除 銀行家演算法作業系統演算法
- 實戰:併發轉賬業務中避免死鎖的各種方法
- Java 中的死鎖Java
- java中避免集合死鏈呼叫Java
- Java執行緒面試題(02) Java執行緒中如何避免死鎖Java執行緒面試題
- 執行緒中的死鎖執行緒
- [C#.NET 拾遺補漏]12:死鎖和活鎖的發生及避免C#
- SQ死鎖及死鎖的解決
- ORACLE中殺死鎖程式的方法Oracle
- Go中協程死鎖Go
- golang 中 channel 的詳細使用、使用注意事項及死鎖分析Golang
- swift FMDB使用Swift
- Oracle中的死鎖Dead Lock(一)Oracle
- Oracle中的死鎖Dead Lock(二)Oracle
- MySQL 行級鎖的使用以及死鎖的預防MySql
- java中死鎖是什麼Java
- MySQL 避免行鎖升級為表鎖——使用高效的索引MySql索引
- Java鎖——死鎖Java
- 死鎖
- 【面試普通人VS高手系列】死鎖的發生原因和怎麼避免面試
- 舉例講解 Python 中的死鎖、可重入鎖和互斥鎖Python
- 阿里二面:如何定位&避免死鎖?連著兩個面試問到了!阿里面試
- 從OS中kill ORACLE死鎖程式Oracle
- MySQL:一個死鎖分析 (未分析出來的死鎖)MySql
- SQL Server 的死鎖SQLServer
- 什麼是死鎖?如何解決死鎖?
- SQLServer的死鎖分析(1):頁鎖SQLServer
- 殺死Oracle死鎖程式Oracle
- MySQL/InnoDB中,樂觀鎖、悲觀鎖、共享鎖、排它鎖、行鎖、表鎖、死鎖概念的理解MySql
- MySQL鎖:InnoDB行鎖需要避免的坑MySql
- 死鎖分析
- oracle 死鎖Oracle
- golang中關於死鎖的思考與學習Golang
- 檢視oracle死鎖程式並結束死鎖Oracle