2015-11-26 23 views
2

這個問題是關於Mongo C++驅動程序的線程安全性的一種跟進this one。作爲參考,我使用驅動程序的legacy-1.0.2 versionMongoDB 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()的情況特別奇怪...這是一個非常簡單的方法,當然不應該失敗(當然除了併發問題)

回答

2

按照你的建議做是不合法的:在內部,DBClientCursor包含一個指向DBClientBase對象,並調用它的方法。因此,您必須將連接保持在池外,直到銷燬遊標。

+0

感謝您的反饋!只剩下一個疑問......你是指「銷燬遊標」是什麼意思?在它上調用kill()操作? – fgalan

+1

更好的做法是隻在DBClientCursor對象的析構函數運行後重新使用連接。 DBClientCursor :: kill方法實際上不會將指向該DBClientBase的指針清零。如果在殺死後無意中在DBClientCursor上調用了另一個方法,則仍然可以競賽。現在,你可能會說你不會那樣做,但唯一確定的方法是通過調用它的dtor來銷燬遊標對象。 – acm

+0

再次感謝您提供如此準確的反饋! – fgalan

相關問題