SQLite多線程使用總結

SQLite支持3種線程模式:
  單線程:這種模式下,沒有進行互斥,多線程使用不安全。禁用全部的mutex鎖,併發使用時會出錯。當SQLite編譯時加了SQLITE_THREADSAFE=0參數,或者在初始化SQLite前調用sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)時啓用。
  多線程:這種模式下,只要一個數據庫鏈接不被多個線程同時使用就是安全的。源碼中是啓用bCoreMutex,禁用bFullMutex。實際上就是禁用數據庫鏈接和prepared statement(準備好的語句)上的鎖,所以不能在多個線程中併發使用同一個數據庫鏈接或prepared statement。當SQLite編譯時加了SQLITE_THREADSAFE=2參數時默認啓用。若SQLITE_THREADSAFE不爲0,能夠在初始化SQLite前,調用sqlite3_config(SQLITE_CONFIG_MULTITHREAD)啓用;或者在建立數據庫鏈接時,設置SQLITE_OPEN_NOMUTEX flag。
  串行:sqlite是線程安全的。啓用全部的鎖,包括bCoreMutex和bFullMutex 。由於數據庫鏈接和prepared statement都已加鎖,因此多線程使用這些對象時無法併發,也就變成串行了。當SQLite編譯時加了SQLITE_THREADSAFE =1參數時默認啓用。若SQLITE_THREADSAFE不爲0,能夠在初始化SQLite前,調用sqlite3_config(SQLITE_CONFIG_SERIALIZED)啓用;或者在建立數據庫鏈接時,設置SQLITE_OPEN_FULLMUTEX flag  。
    而這裏所說的初始化是指調用sqlite3_initialize()函數,這個函數在調用sqlite3_open()時會自動調用,且只有第一次調用是有效的.
 
   爲了達到線程安全,SQLite在編譯時必須將 SQLITE_THREADSAFE 預處理宏置爲1。在Windows和Linux上, 已編譯的好的二進制發行版中都是這樣設置的。 若是不肯定你所使用的庫是不是線程安全的,能夠調用 sqlite3_threadsafe() 接口找出。調用sqlite3_threadsafe()能夠得到編譯期的SQLITE_THREADSAFE參數 。
 
   也就是說線程模式能夠在編譯時(經過源碼編譯sqlite庫時)、啓動時(使用sqlite的應用程序初始化時)或者運行時(建立數據庫鏈接時)來指定。通常而言,運行時指定的模式將覆蓋啓動時的指定模式,啓動時指定的模式將覆蓋編譯時指定的模式。可是,單線程模式一旦被指定,將沒法被覆蓋。默認的線程模式是串行模式。
 
 
編譯時選擇線程模式
    能夠經過定義SQLITE_THREADSAFE宏來指定線程模式。若是沒有指定,默認爲串行模式。定義宏SQLITE_THREADSAFE=1指定使用串行模式;=0使用單線程模式;=2使用多線程模式。
    sqlite3_threadsafe()函數的返回值能夠肯定編譯時指定的線程模式。若是指定了單線程模式,函數返回false。若是指定了串行或者多線程模式,函數返回true。因爲sqlite3_threadsafe()函數要早於多線程模式以及啓動時和運行時的模式選擇,因此它既不能區別多線程模式和串行模式也不能區別啓動時和運行時的模式。
    最後一句可經過sqlite3_threadsafe函數的實現來理解SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }若是編譯時指定了單線程模式,那麼臨界互斥邏輯在構造時就被省略,所以也就沒法在啓動時或運行時指定串行模式或多線程模式。
 
啓動時選擇線程模式
    假如在編譯時沒有指定單線程模式,就能夠在應用程序初始化時使用sqlite3_config()函數修改線程模式。參數SQLITE_CONFIG_SINGLETHREAD可指定爲
單線程模式,SQLITE_CONFIG_MULTITHREAD指定爲多線程模式,SQLITE_CONFIG_SERIALIZED指定爲串行模式。
 
運行時選擇線程模式
    若是沒有在編譯時和啓動時指定爲單線程模式,那麼每一個數據庫鏈接在建立時可單獨的被指定爲多線程模式或者串行模式,可是不能指定爲單線程模式。若是在編譯時或啓動時指定爲單線程模式,就沒法在建立鏈接時指定多線程或者串行模式。
    建立鏈接時用sqlite3_open_v2()函數的第三個參數來指定線程模式。SQLITE_OPEN_NOMUTEX標識建立多線程模式的鏈接;SQLITE_OPEN_FULLMUTEX標識建立串行模式的鏈接。若是沒有指定標識,或者使用sqlite3_open()或sqlite3_open16()函數來建立數據庫鏈接,那麼在編譯時或啓動時指定的線程模式將做爲默認的線程模式使用。
相關文章
相關標籤/搜索