線程局部存儲(chǔ)在其它語言中都是以庫的形式提供的(庫函數(shù)或類)。但在C++11中以關(guān)鍵字的形式,做為一種存儲(chǔ)類型出現(xiàn),由此可見C++11對(duì)線程局部存儲(chǔ)的重視。C++11中有如下幾種存儲(chǔ)類型:
| 序號(hào) | 類型 | 備注 |
|---|---|---|
| 1 | auto | 該關(guān)鍵字用于兩種情況: 1. 聲明變量時(shí): 根據(jù)初始化表達(dá)式自動(dòng)推斷變量類型。 2. 聲明函數(shù)作為函數(shù)返回值的占位符。 |
| 2 | static | static變量只初始化一次,除此之外它還有可見性的屬性: 1. static修飾函數(shù)內(nèi)的“局部”變量時(shí),表明它不需要在進(jìn)入或離開函數(shù)時(shí)創(chuàng)建或銷毀。且僅在函數(shù)內(nèi)可見。 2. static修飾全局變量時(shí),表明該變量僅在當(dāng)前(聲明它的)文件內(nèi)可見。 3. static修飾類的成員變量時(shí),則該變量被該類的所有實(shí)例共享。 |
| 3 | register | 寄存器變量。該變量存儲(chǔ)在CPU寄存器中,而不是RAM(?;蚨?中。該變量的最大尺寸等于寄存器的大小。由于是存儲(chǔ)于寄存器中,因此不能對(duì)該變量進(jìn)行取地址操作。 |
| 4 | extern | 引用一個(gè)全局變量。當(dāng)在一個(gè)文件中定義了一個(gè)全局變量時(shí),就可以在其它文件中使用extern來聲明并引用該變量。 |
| 5 | mutable | 僅適用于類成員變量。以mutable修飾的成員變量可以在const成員函數(shù)中修改。參見上一章chan.simple.h中對(duì)mutex的使用。 |
| 6 | thread_local | 線程周期 |
thread_local修飾的變量具有如下特性:
- 變量在線程創(chuàng)建時(shí)生成(不同編譯器實(shí)現(xiàn)略有差異,但在線程內(nèi)變量第一次使用前必然已構(gòu)造完畢)。
- 線程結(jié)束時(shí)被銷毀(析構(gòu),利用析構(gòu)特性,thread_local變量可以感知線程銷毀事件)。
- 每個(gè)線程都擁有其自己的變量副本。
- thread_local可以和static或extern聯(lián)合使用,這將會(huì)影響變量的鏈接屬性。
下面代碼演示了thread_local變量在線程中的生命周期
// thread_local.cpp
#include <iostream>
#include <thread>
class A {
public:
A() {
std::cout << std::this_thread::get_id()
<< " " << __FUNCTION__
<< "(" << (void *)this << ")"
<< std::endl;
}
~A() {
std::cout << std::this_thread::get_id()
<< " " << __FUNCTION__
<< "(" << (void *)this << ")"
<< std::endl;
}
// 線程中,第一次使用前初始化
void doSth() {
}
};
thread_local A a;
int main() {
a.doSth();
std::thread t([]() {
std::cout << "Thread: "
<< std::this_thread::get_id()
<< " entered" << std::endl;
a.doSth();
});
t.join();
return 0;
}
運(yùn)行該程序
$> g++ -std=c++11 -o debug/tls.out ./thread_local.cpp
$> ./debug/tls.out
01 A(0xc00720)
Thread: 02 entered
02 A(0xc02ee0)
02 ~A(0xc02ee0)
01 ~A(0xc00720)
$>
變量a在main線程和t線程中分別保留了一份副本,以下時(shí)序圖表明了兩份副本的生命周期。
| 上一篇 C++11多線程-異步運(yùn)行 |
目錄 | 下一篇 C++11多線程-原子操作(1) |
|---|