2010-11-30 82 views
5

幾個月前,我遇到了一個人(orkut)提出的這個有趣的場景。儘管如此,我已經想出了一個針對這個問題的「非便攜式」解決方案(已經用小代碼對其進行了測試),但仍然想知道你們有什麼要說的和建議的。場景:多線程應用程序使用的DLL中的全局變量

假設我創建了一個DLL,導出一些用C++編寫的功能,用於單線程客戶端。這個DLL聲明瞭大量的全局變量,其中一些可能是const變量(只讀),而另一些是可以修改的。無論如何,後來的事情發生了變化,現在我想讓相同的DLL與多線程應用程序(不需要修改DLL)一起工作。這意味着,幾個線程從DLL訪問函數和全局變量,並修改它們......等等。所有這些都可能導致全局變量保持不一致的值。

所以現在的問題是,

我們可以做一些客戶端代碼,以防止DLL的多接入,並在同一時間,確保每個線程在它自己的上下文(意運行,當它訪問DLL時,DLL的全局值與以前相同)?

+0

如果您至少可以重建DLL,您可以將__declspec(threadlocal)添加到所有全局定義中。我強烈懷疑在構造函數或析構函數的靜態範圍類對象上會失敗。 – 2010-11-30 12:30:58

+0

Chris ...不,我們不能將__declspec(threadlocal)添加到全局變量,因爲不允許修改源代碼。 :-) – Nawaz 2010-11-30 14:05:15

回答

1

我們可以在客戶端代碼中做些什麼來防止DLL的多重訪問,並且同時確保每個線程運行在它自己的上下文中(也就是說,當它訪問DLL時, DLL的全局值與以前相同)?

這是難的部分。我認爲頂層做這件事的唯一方法就是圍繞現有的DLL創建一個包裝。當它被調用時,它會恢復當前線程的狀態(全局變量),並在對DLL的調用返回時保存它們。您需要知道DLL中的所有狀態變量,並且能夠讀取/寫入它們。

如果性能不是問題,整個DLL的單個鎖就足夠了,並且是最容易正確實現的。這將確保只有一個線程同時訪問(讀取或寫入)DLL。

2

當然,你總是可以創建一個處理多線程特定任務(如鎖定)的包裝層。您甚至可以在與原始鏈接的第二個DLL中執行此操作,然後將該最終項目鏈接與該新DLL關聯。

請注意,無論您如何實施它,這都不是一件容易的事。您必須確切知道哪個線程能夠在什麼時間修改哪個值,誰能夠讀取什麼以及何時等,除非您想要遇到死鎖或競態條件等問題。

如果您的解決方案允許它,通常最好指定一個線程來修改任何數據,並讓所有其他人只讀並不寫,因爲併發讀取訪問總是比並發寫入訪問更容易實現(Boost提供了所有基本功能,例如shared_mutex)。