2011-09-30 41 views
19

Cách xác định biến tĩnh cục bộ (giữ giá trị của nó giữa các cuộc gọi hàm) không được chia sẻ giữa các luồng khác nhau?Làm thế nào để xác định các biến tĩnh cục bộ luồng cục bộ?

Tôi đang tìm kiếm một câu trả lời cả trong C và C++

+0

Bạn đang sử dụng hệ điều hành nào? TLS không di động giữa các cửa sổ và unixen. – bdonlan

+3

C++ 11 giới thiệu một thời lượng lưu trữ khác gọi là ['thread_local'] (http://en.cppreference.com/w/cpp/language/storage_duration). Hãy thử sử dụng nó. – Nawaz

+0

Hệ điều hành là các cửa sổ ... –

Trả lời

9

trên Windows sử dụng Windows API: TlsAlloc()/TlsSetValue()/TlsGetValue()

trên Windows sử dụng trình biên dịch nội tại: sử dụng _declspec(thread)

trên Linux (khác POSIX? ??): get_thread_area() và có liên quan

+0

sau khi đọc trên MSDN, hàm Tls chính xác là những gì tôi đang tìm kiếm. –

+2

bạn quên TlsFree :-) –

2

Tiêu chuẩn C hiện tại không có mô hình cho đề hay như nhau, vì vậy bạn không thể có được một câu trả lời, có.

Tiện ích được POSIX đoán trước là pthread_[gs]etspecific.

Phiên bản tiếp theo của tiêu chuẩn C thêm chủ đề và có khái niệm về bộ nhớ cục bộ địa chỉ.

-3

Bạn có thể tạo cấu trúc dữ liệu được phân bổ từ heap cho mỗi chuỗi.

Ví dụ:

struct ThreadLocal 
{ 
    int var1; 
    float var2; 
    //etc.. 
} 
8

Chỉ cần sử dụng hàm tĩnh và __thread trong hàm của bạn.

Ví dụ:

int test(void) 
{ 
     static __thread a; 

     return a++; 
} 
+3

là __thread standard? –

+2

@Ali: không, đó là phần mở rộng được cung cấp bởi GCC và một vài trình biên dịch khác. Trên MSVC, tôi nghĩ bạn sử dụng '__declspec (thread)' thay thế. –

+3

__thread hoạt động trên linux, bsd, aix và với các trình biên dịch xl_c, gcc và nhiều trình biên dịch khác. nó có thể được trivially #defined để __declspec (thread) trên windows. –

1

Bạn có thể làm của riêng chủ đề lưu trữ địa phương cụ thể của bạn như singleton mỗi thread ID. Một cái gì đó như thế này:

struct ThreadLocalStorage 
{ 
    ThreadLocalStorage() 
    { 
     // initialization here 
    } 
    int my_static_variable_1; 
    // more variables 
}; 

class StorageManager 
{ 
    std::map<int, ThreadLocalStorage *> m_storages; 

    ~StorageManager() 
    { // storage cleanup 
     std::map<int, ThreadLocalStorage *>::iterator it; 
     for(it = m_storages.begin(); it != m_storages.end(); ++it) 
      delete it->second; 
    } 

    ThreadLocalStorage * getStorage() 
    { 
     int thread_id = GetThreadId(); 
     if(m_storages.find(thread_id) == m_storages.end()) 
     { 
      m_storages[thread_id] = new ThreadLocalStorage; 
     } 

     return m_storages[thread_id]; 
    } 

public: 
    static ThreadLocalStorage * threadLocalStorage() 
    { 
     static StorageManager instance; 
     return instance.getStorage(); 
    } 
}; 

GetThreadId(); là một chức năng nền tảng cụ thể để xác định id của người gọi. Một cái gì đó như thế này:

int GetThreadId() 
{ 
    int id; 
#ifdef linux 
    id = (int)gettid(); 
#else // windows 
    id = (int)GetCurrentThreadId(); 
#endif 
    return id; 
} 

Bây giờ, trong vòng một chức năng chủ đề mà bạn có thể sử dụng nó lưu trữ địa phương:

void threadFunction(void*) 
{ 
    StorageManager::threadLocalStorage()->my_static_variable_1 = 5; //every thread will have 
                  // his own instance of local storage. 
} 
+0

Bạn cũng sẽ cần đồng bộ hóa (chẳng hạn như đọc/ghi mutex) để bảo vệ 'm_storages' khỏi truy cập bởi nhiều luồng. –

+0

tất nhiên. bạn nói đúng. – GreenScape

+0

Không chỉ m_storages, mà còn std :: map và "instance StorageManager tĩnh" cục bộ; không phải là chủ đề an toàn. Trong mã nguồn gốc thực hiện một singleton hiệu quả cao không phải là một nhiệm vụ dễ dàng, xem "C + + và Perils của Double-Checked Locking" của Scott Meyers và Andrei Alexandrescu. http://erdani.com/publications/DDJ_Jul_Aug_2004_revised.pdf – zhaorufei

2

Bạn cũng có thể sử dụng C++ 11 chủ đề bổ sung lưu trữ địa phương nếu bạn có quyền truy cập vào C++ 11.

Các vấn đề liên quan