這個問題是關於Mongo C++驅動程序的線程安全性的一種跟進this one。作爲參考,我使用驅動程序的legacy-1.0.2 version。MongoDB C++驅動程序的線程安全性通過光標間接連接使用
因此,閱讀這個問題的答案後,很顯然,這不是安全的兩個線程在同一時間同一DBClientConnection
使用。但是,由於光標引起的「間接」連接使用情況呢?讓我來舉個例子來解釋一下。
考慮一個帶有連接池的程序(即一個DBClientConnection
對象的數組),並確保一次只有一個線程使用該池的給定實例。讓我們考慮以下情況:
- 線程T1從池中獲取連接C1。除了T1之外,沒有人從那時開始接觸C1。
- 線程T1使用C1執行
query()
操作並獲取DBClientCursor
對象(我們將其命名爲U1)。要清楚,我指的是this particular operation。 - 線程T1將C1返回給池,因爲一旦U1對象被get,連接對象itsef就不再對他有用。
- T1開始在長循環
while(u1->more())
循環中處理U1的結果。假設光標很大,並不是所有結果都可以在第一組中返回(在接線協議級別),所以需要連接到DB以通過驅動程序實現的網絡佈線協議返回新結果。 - 當T1正在完成這項工作時,新線程(T2)從池中獲取C1,即T1先前使用的連接。
- T2在使用C1時執行一些操作,而T1仍在使用U1(通過C1生成的遊標)。
請問這種情況是有問題的?雖然程序履行線程safeness「合同」關於DBClientConnection
對象(在一個時間,即只有一個線程可以訪問相同的DBClientCursor
實例)(即只一次一個線程可以訪問相同的DBClientConnection
實例)和DBClientCursor
,由於光標可能會間接併發訪問相同的連接(在內部級別),我不知道這是否會成爲問題。
理這個問題的:我有可能發生上述情況的程序,我越來越怪異和半隨機崩潰,由於在異常DBClientCursor
方法,特別是next()/nextSafe()
和more()
。 more()
的情況特別奇怪...這是一個非常簡單的方法,當然不應該失敗(當然除了併發問題)
感謝您的反饋!只剩下一個疑問......你是指「銷燬遊標」是什麼意思?在它上調用kill()操作? – fgalan
更好的做法是隻在DBClientCursor對象的析構函數運行後重新使用連接。 DBClientCursor :: kill方法實際上不會將指向該DBClientBase的指針清零。如果在殺死後無意中在DBClientCursor上調用了另一個方法,則仍然可以競賽。現在,你可能會說你不會那樣做,但唯一確定的方法是通過調用它的dtor來銷燬遊標對象。 – acm
再次感謝您提供如此準確的反饋! – fgalan