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~
對了
覺得有用
掃碼關注
點個在看
你的支持是我搬磚的動力
我是陳同學
讓技術
有溫度