女朋友也能看懂的TLS技術講解

FBI Warning


硬核預警:

本文需要一定的
多線程基礎知識
沒學過的小夥伴也沒關係
本文將會通俗的講解
說不定看着看着你就懂了呢
 

Q:

啥叫TLS ?     特侖蘇?

A:

。。。。

要知道啥叫TLS 
先得知道它要用來解決啥問題


我們知道在一個進程中,
所有線程是共享同一個地址空間的。


所以,如果一個變量是全局變量
那麼所有線程訪問的是同一份


如果某一個線程對其進行了修改
也就會影響到其他所有的線程
不過我們可能並不希望這樣,


例如linux下的全局變量 errno,
線程A在設置了一個錯誤信息後,
線程B又設置了一個錯誤信息,
前一個線程設置的信息就被覆蓋了

那有沒有辦法保證在多線程程序中能訪問而不互相影響呢
答案是有的。


操作系統幫我們提供了這個功能
TLS(Thread Local Storage)線程本地存儲。
TLS的作用是能將數據和執行的特定的線程聯繫起來。

所以上面的那個問題解決方法就是
將這個全局變量設置爲TLS變量

這樣在用戶看來雖然errno是一個全局變量,
但實際上它是每個線程獨立的。
我們就是需要依賴全局變量或者靜態變量,

Q:

還是沒大明白....... 有沒有課代表給總結一下

A:

總結一下就是


就是一個全局或者靜態變量

但是把這個全局變量聲明爲TLS變量以後  

它會在每個線程都有一個副本,
在不同的線程中可以可以按照相同的方式來訪問,

既然是都有副本,自然線程中互不影響

Q:

哦  ......就比如一個人,被分身出了三個,其中一個被砍了一刀,其它兩人都不會受傷。

A:

可以這樣理解

Q:

TLS變量 = 影 流 之 主   ?

A:

WTF  ?  ? ?  ?

Q:

有沒有嚴格的定義?

A:

TLS是一種在多線程時使用的技術,
它可以使你的全局變量、靜態變量以及局部靜態、靜態成員變量
成爲線程獨立的變量,
即每個線程的TLS變量之間互不影響。 

就像對待自身的局部變量一樣。

Q:

emm.........光看理論還真是讓人枯燥鴨.... Talk is cheap  Show me the code

A:

得嘞...... 下面就教你怎麼用 

其實用想用TLS 變量其實很簡單

直接在全局變量聲明前加個 __thread關鍵字就可以 

像下面這樣

Q:

只有這一種使用方法嗎?

A:

其實上面只是最簡單的一種使用方法

TLS的使用其實分爲兩種方式   靜態的和動態的


靜態的TLS

直接用語言本身的關鍵字去定義

在C/C++裏面主要有這幾個關鍵字  

1.__thread

2.thread_local 

3.__declspec (thread)  

第三個關鍵字主要在visual c++編譯器下使用 

在g++/gcc編譯器下用不了(實測)

使用方法和剛纔說的一樣

動態的TLS

調用系統的API去創建的 而不是用語言本身的關鍵字
 而linux和windows調用的api又有所不同

可以自行查一下維基百科 

這裏不作贅述 

Q:

 老鐵  有沒有啥具體的例子  ???

A:

好滴 老闆

給你兩個

一看就懂的例子

沒有加TLS

有加TLS

Q: 哦 ....聽你這麼一說我大概會用了 ,那今天就到這吧 

A:

少俠慢走!!!

學東西得知其然知其所以然 

TLS這種強大的技術

難道你就不好奇它是怎麼實現的嗎?

Q:

emm.....行吧  那你再給我嘮嘮它的原理

A:

線程局部存儲在不同的平臺有不同的實現,可移植性不太好。

幸好要實現線程局部存儲並不難,

最簡單的辦法就是建立一個全局表,

通過當前線程ID去查詢相應的數據,因爲各個線程的ID不同,

查到的數據自然也不同了。

但Windows系統採用了每個線程建線程專享的索引表,

表的條目爲線程局部存儲的地址。

在線程執行的任何代碼處,

都可以查詢本線程的這個索引表獲得

要訪問的線程局部存儲的地址。

大多數平臺都提供了線程局部存儲的方法,

無需要我們自己去實現:

Q:

恩恩 通透 ....現在算是知道他是用在哪 怎麼用  啥原理了

A:

只要你明白了就好 

下次有問題 可以後臺私信我 
我也要搬磚去了   bye~

對了 

覺得有用

掃碼關注 

點個在看 

你的支持是我搬磚的動力


我是陳同學
讓技術 
有溫度

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章