簡體   English   中英

如何安全地與不同編譯單元中的線程共享變量?

[英]How do I safely share a variable with a thread that is in a different compilation unit?

在我的程序結構中,我將“調用它的位置”和“完成了什么”划分為單獨的源文件。 作為實用性問題,這允許我將程序作為獨立程序編譯或將其包含在 DLL 中。 下面的代碼不是實際代碼,而是一個簡化的示例,說明了同樣的問題。

這里有 3 個交互組件:kernel 模式程序,它加載我的 DLL、DLL 及其源文件和實用程序及其源,分別維護。

在 DLL 表單中,程序作為線程加載。 According to the kernel mode application vendor's documentation, I loose the ability to call Win32 API functions after the initialization of the kernel program so I load the thread as an active thread (as opposed to using CREATE_SUSPENDED since I can't wake it).

我讓它監視一個標志變量,以便它知道何時通過一個不優雅但功能強大的東西做一些有用的事情:

while ( pauseThreadFlag ) Sleep(1000);

最多 1 秒的延遲是可以接受的(整個過程很長,而且很少調用),並且似乎不會影響系統。

在線程源文件中,我將變量聲明為

volatile bool pauseThreadFlag = true;

在我聲明的 DLL 源文件中

extern volatile bool pauseThreadFlag;

當我准備好執行線程時,在 DLL 我設置

pauseThreadFlag = false;

我在將 std::string 對象聲明為 volatile 時遇到了一些困難,因此我將我的參數聲明為線程源文件中的全局變量,並擁有駐留在線程源中的 DLL 調用設置器。 如果我可以隨意實例化線程,這些字符串將是參數。

(所有這一切都缺少鎖定變量以確保線程安全,這是我的下一個“要做的事情”)

這讓我覺得這是一個糟糕的設計......它的功能性但令人費解。 鑒於我提到的限制,go 是否有更好的方法來解決這個問題?

我在想一個可能的修改是使用在線程創建時給出的 LPVOID lpParams 變量來保存指向字符串對象的指針,即使創建線程時字符串是空的,並且直接從線程訪問它們,這樣完全刪除線程程序中的聲明、設置器等? 如果這可行,那么也可以在那里引用暫停標志,並消除外部聲明(但我認為它仍然需要聲明為 volatile 以提示優化器)。

如果有任何區別,環境是 Visual Studio 2010,C++,目標平台 Win32 (XP)。

謝謝!

如果所有組件都在 kernel 模式下運行,您將需要查看KeInitializeEventKeSetEventKeResetEventKeWaitForSingleObject 這些都以與其等效的用戶模式類似的方式工作。

我最終刪除了該結構並將其替換為封裝所有數據的 object。 這有點可怕,充滿了 getter 和 setter,但在這種特殊情況下,我使用訪問方法來確保正確設置/取消設置鎖。

使用指向此 object 的 void 強制轉換指針正確地通過了 object,它看起來相當穩定。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM