深入SQLite多線程的使用總結(jié)詳解
SQLite支持3種線程模式:
單線程:這種模式下,沒(méi)有進(jìn)行互斥,多線程使用不安全。禁用所有的mutex鎖,并發(fā)使用時(shí)會(huì)出錯(cuò)。當(dāng)SQLite編譯時(shí)加了SQLITE_THREADSAFE=0參數(shù),或者在初始化SQLite前調(diào)用sqlite3_config(SQLITE_CONFIG_SINGLETHREAD)時(shí)啟用。
多線程:這種模式下,只要一個(gè)數(shù)據(jù)庫(kù)連接不被多個(gè)線程同時(shí)使用就是安全的。源碼中是啟用bCoreMutex,禁用bFullMutex。實(shí)際上就是禁用數(shù)據(jù)庫(kù)連接和prepared statement(準(zhǔn)備好的語(yǔ)句)上的鎖,因此不能在多個(gè)線程中并發(fā)使用同一個(gè)數(shù)據(jù)庫(kù)連接或prepared statement。當(dāng)SQLite編譯時(shí)加了SQLITE_THREADSAFE=2參數(shù)時(shí)默認(rèn)啟用。若SQLITE_THREADSAFE不為0,可以在初始化SQLite前,調(diào)用sqlite3_config(SQLITE_CONFIG_MULTITHREAD)啟用;或者在創(chuàng)建數(shù)據(jù)庫(kù)連接時(shí),設(shè)置SQLITE_OPEN_NOMUTEX flag。
串行:sqlite是線程安全的。啟用所有的鎖,包括bCoreMutex和bFullMutex 。因?yàn)閿?shù)據(jù)庫(kù)連接和prepared statement都已加鎖,所以多線程使用這些對(duì)象時(shí)沒(méi)法并發(fā),也就變成串行了。當(dāng)SQLite編譯時(shí)加了SQLITE_THREADSAFE =1參數(shù)時(shí)默認(rèn)啟用。若SQLITE_THREADSAFE不為0,可以在初始化SQLite前,調(diào)用sqlite3_config(SQLITE_CONFIG_SERIALIZED)啟用;或者在創(chuàng)建數(shù)據(jù)庫(kù)連接時(shí),設(shè)置SQLITE_OPEN_FULLMUTEX flag 。
而這里所說(shuō)的初始化是指調(diào)用sqlite3_initialize()函數(shù),這個(gè)函數(shù)在調(diào)用sqlite3_open()時(shí)會(huì)自動(dòng)調(diào)用,且只有第一次調(diào)用是有效的.
為了達(dá)到線程安全,SQLite在編譯時(shí)必須將 SQLITE_THREADSAFE 預(yù)處理宏置為1。在Windows和Linux上, 已編譯的好的二進(jìn)制發(fā)行版中都是這樣設(shè)置的。如果不確定你所使用的庫(kù)是否是線程安全的,可以調(diào)用 sqlite3_threadsafe() 接口找出。調(diào)用sqlite3_threadsafe()可以獲得編譯期的SQLITE_THREADSAFE參數(shù) 。
也就是說(shuō)線程模式可以在編譯時(shí)(通過(guò)源碼編譯sqlite庫(kù)時(shí))、啟動(dòng)時(shí)(使用sqlite的應(yīng)用程序初始化時(shí))或者運(yùn)行時(shí)(創(chuàng)建數(shù)據(jù)庫(kù)連接時(shí))來(lái)指定。一般而言,運(yùn)行時(shí)指定的模式將覆蓋啟動(dòng)時(shí)的指定模式,啟動(dòng)時(shí)指定的模式將覆蓋編譯時(shí)指定的模式。但是,單線程模式一旦被指定,將無(wú)法被覆蓋。默認(rèn)的線程模式是串行模式。
編譯時(shí)選擇線程模式
可以通過(guò)定義SQLITE_THREADSAFE宏來(lái)指定線程模式。如果沒(méi)有指定,默認(rèn)為串行模式。定義宏SQLITE_THREADSAFE=1指定使用串行模式;=0使用單線程模式;=2使用多線程模式。
sqlite3_threadsafe()函數(shù)的返回值可以確定編譯時(shí)指定的線程模式。如果指定了單線程模式,函數(shù)返回false。如果指定了串行或者多線程模式,函數(shù)返回true。由于sqlite3_threadsafe()函數(shù)要早于多線程模式以及啟動(dòng)時(shí)和運(yùn)行時(shí)的模式選擇,所以它既不能區(qū)別多線程模式和串行模式也不能區(qū)別啟動(dòng)時(shí)和運(yùn)行時(shí)的模式。
最后一句可通過(guò)sqlite3_threadsafe函數(shù)的實(shí)現(xiàn)來(lái)理解SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }如果編譯時(shí)指定了單線程模式,那么臨界互斥邏輯在構(gòu)造時(shí)就被省略,因此也就無(wú)法在啟動(dòng)時(shí)或運(yùn)行時(shí)指定串行模式或多線程模式。
啟動(dòng)時(shí)選擇線程模式
假如在編譯時(shí)沒(méi)有指定單線程模式,就可以在應(yīng)用程序初始化時(shí)使用sqlite3_config()函數(shù)修改線程模式。參數(shù)SQLITE_CONFIG_SINGLETHREAD可指定為
單線程模式,SQLITE_CONFIG_MULTITHREAD指定為多線程模式,SQLITE_CONFIG_SERIALIZED指定為串行模式。
運(yùn)行時(shí)選擇線程模式
如果沒(méi)有在編譯時(shí)和啟動(dòng)時(shí)指定為單線程模式,那么每個(gè)數(shù)據(jù)庫(kù)連接在創(chuàng)建時(shí)可單獨(dú)的被指定為多線程模式或者串行模式,但是不能指定為單線程模式。如果在編譯時(shí)或啟動(dòng)時(shí)指定為單線程模式,就無(wú)法在創(chuàng)建連接時(shí)指定多線程或者串行模式。
創(chuàng)建連接時(shí)用sqlite3_open_v2()函數(shù)的第三個(gè)參數(shù)來(lái)指定線程模式。SQLITE_OPEN_NOMUTEX標(biāo)識(shí)創(chuàng)建多線程模式的連接;SQLITE_OPEN_FULLMUTEX標(biāo)識(shí)創(chuàng)建串行模式的連接。如果沒(méi)有指定標(biāo)識(shí),或者使用sqlite3_open()或sqlite3_open16()函數(shù)來(lái)創(chuàng)建數(shù)據(jù)庫(kù)連接,那么在編譯時(shí)或啟動(dòng)時(shí)指定的線程模式將作為默認(rèn)的線程模式使用。
相關(guān)文章
MyBatis中的SQL映射文件配置結(jié)果映射的操作指南
MyBatis?是一款優(yōu)秀的?ORM?框架,它提供了多種配置方式來(lái)定義?SQL?語(yǔ)句以及結(jié)果映射規(guī)則,本文將介紹?MyBatis?中的?SQL?映射文件如何配置結(jié)果映射,包括常規(guī)類型、集合類型等多種情況,需要的朋友可以參考下2023-07-07springMVC如何將controller中Model數(shù)據(jù)傳遞到j(luò)sp頁(yè)面
本篇文章主要介紹了springMVC如何將controller中Model數(shù)據(jù)傳遞到j(luò)sp頁(yè)面,具有一定的參考價(jià)值,有興趣的可以了解一下2017-07-07細(xì)談java同步之JMM(Java Memory Model)
Java內(nèi)存模型是在硬件內(nèi)存模型上的更高層的抽象,它屏蔽了各種硬件和操作系統(tǒng)訪問(wèn)的差異性,保證了Java程序在各種平臺(tái)下對(duì)內(nèi)存的訪問(wèn)都能達(dá)到一致的效果。下面我們來(lái)一起學(xué)習(xí)下JMM2019-05-05Java每7天日志自動(dòng)清理的項(xiàng)目實(shí)踐
在實(shí)際項(xiàng)目中由于服務(wù)器內(nèi)存有限,人工清理常會(huì)忘記,本文主要介紹了Java每7天日志自動(dòng)清理的項(xiàng)目實(shí)踐,具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01Spring?Boot中@Autowired注入為空的原因以及解決方法
最近在開(kāi)發(fā)中遇到了使用@Autowired注解自動(dòng)裝配時(shí)會(huì)報(bào)空指針,發(fā)現(xiàn)對(duì)象并沒(méi)有裝配進(jìn)來(lái),下面這篇文章主要給大家介紹了關(guān)于Spring?Boot中@Autowired注入為空的原因以及解決方法,需要的朋友可以參考下2024-01-01mybatis-plus批量更新updateBatchById問(wèn)題
這篇文章主要介紹了mybatis-plus批量更新updateBatchById問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07