[英]How to link non thread-safe library so each thread will have its own global variables from it?
我有一個程序,我鏈接到許多庫。 我在profiler上運行我的應用程序,發現在一些網絡請求之后大部分時間都花在“等待”狀態。 這些請求是我的代碼從外部庫調用sleeping_function()
效果。 我在循環中調用此函數,該循環執行許多次,因此所有等待時間總計達到大量。
由於我無法修改sleeping_function()
我想啟動一些線程並行地運行我的循環的幾次迭代。 問題是這個函數在內部使用了一些全局變量。
有沒有辦法告訴SunOS上的鏈接器我想以某種方式鏈接特定的庫,將所有變量放在線程本地存儲中?
我不認為你只能使用鏈接器來實現這一點,但是你可能能夠在C中使用某些代碼。
問題是加載已加載庫的調用將返回對已加載實例的引用,而不是加載新副本。 快速查看dlopen和LoadLibrary的文檔似乎確認無法多次加載同一個庫,至少在您希望圖像准備好執行時是這樣。 避免這種情況的一種方法是阻止操作系統知道它是同一個庫。 為此,您可以復制該文件。
一些偽代碼,只需通過調用call_sleeping_function_thread_safe
來替換對sleeping_function
的調用:
char *shared_lib_name
void sleeping_function_thread_init(char *lib_name);
void call_sleeping_function_thread_safe()
{
void *lib_handle;
pthread_t pthread;
new_file_name = make_copy_of_file(shared_lib_name);
pthread_create(&pthread, NULL, sleeping_function_thread_init, new_file_name);
}
void sleeping_function_thread_init(char *lib_name)
{
void *lib_handle;
void (*)() sleeping_function;
lib_handle = dlopen(lib_name, RTLD_LOCAL);
sleeping_function = dlsym(lib_handle, "sleeping_function")
while (...)
sleeping_function;
dlclose(lib_handle);
delete_file(lib_name);
}
對於Windows, dlopen
變為LoadLibrary
而dlsym
變為GetProcAddress
等......但基本思想仍然可行。
一般來說,這是一個壞主意。 全局數據不是唯一可能阻止非線程安全庫在多線程環境中運行的問題。
作為一個示例,如果庫具有指向內存映射文件的全局變量,它總是映射到單個硬編碼地址。 在這種情況下,使用您的技術,每個線程將有一個全局變量,但它們都指向相同的內存位置,這將被多線程訪問所破壞。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.