從Linux的errno到Java的ThreadLocal

來源:互聯網
上載者:User

標籤:errno   java   linux   threadlocal   線程變數   

Linux裡的errno

在Linux下執行系統調用時,一般會有一個傳回值表示成功或失敗,但是這個值只說明了成功或失敗,卻沒有說明是如何成功或失敗的。

errno就是為瞭解決這個問題的,系統調用會把錯誤號碼設定為errno,我們通過錯誤號碼就能知道失敗的原因。還可以使用strerror列印出這個錯誤號碼對應的字串說明。老版本的Linux需要加上extern int errno,現在直接引入<errno.h>就行了.

errno樣本:

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/6F/6A/wKioL1WbuPjQ9_gzAAHrJFspGzI545.jpg" title="選區_002.png" alt="wKioL1WbuPjQ9_gzAAHrJFspGzI545.jpg" />

現在的問題來了。假如我有兩個線程,代碼如下:

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/6F/6D/wKiom1Wbt2CSHc8DAAC4FjSCW0c854.jpg" title="選區_011.png" alt="wKiom1Wbt2CSHc8DAAC4FjSCW0c854.jpg" />

errno是一個全域變數,那麼假如執行順序為 1-1,2-1,1-2,2-2,線程1列印出的errno就是線程2的,這就是errno的問題,線程不安全。

但是測試很多次,結果都是正確的。雖然你用這個errno是當作一個全域變數的,但是實際上是個宏。用gcc -E將原始碼的宏展開,可以看到,errno被替換成了一個函數。

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M02/6F/6A/wKioL1WbuZuyhJVTAAJJJiKqJHo234.jpg" title="選區_003.png" alt="wKioL1WbuZuyhJVTAAJJJiKqJHo234.jpg" />

使用man errno查看對errno的解釋,可以看到下面一句話:

       errno  is  defined  by  the ISO C standard to be a modifiable lvalue of
       type int, and must not be explicitly declared; errno may  be  a  macro.
       errno  is  thread-local;  setting  it in one thread does not affect its
       value in any other thread.

所以errno並不是一個全域變數,而是一個thread-local,每個線程都有一個。我們可以自己實現一個errno。


自己寫一個errno

僅僅示範一下errno的基本原理,使用一個map存放各個線程的errno,而這個map的key就是threadId。系統調用執行完畢後,會將錯誤碼寫入此線程對應的errno中。代碼中的系統調用是一個假系統調用,some_system_call()。

實際開發中,對於開發人員,他實際上是看不到set_errno(),get_errno()這些函數的,他只需要取errno就行了。

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/6F/6D/wKiom1Wbudzhz-3IAAUruAEgEOY812.jpg" title="選區_007.png" alt="wKiom1Wbudzhz-3IAAUruAEgEOY812.jpg" />


Java的ThreadLocal

Java的ThreadLocal和Linux的errno是一樣的,只不過errno對開發人員來說更簡單一點,而且只能取,當作一個變數就行了。

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/6F/6A/wKioL1WbvwTCsMG7AAI8sT9dyJo690.jpg" title="選區_013.png" alt="wKioL1WbvwTCsMG7AAI8sT9dyJo690.jpg" />

只定義了一個ThreadLocal,但是各個線程裡的都不一樣。

自己實現一個ThreadLocal

其實ThreadLocal也和上面我自己實現的errno類似,用了一個Map,感興趣的可以去看一下jdk源碼,我寫了一個很簡陋的MyThreadLocal,Java的ThreadLocal的原理大致就是這樣的。直接將上面的代碼的ThreadLocal替換成MyThreadLocal就可以運行,當然這個MyThreadLocal太簡單,僅僅為了介紹原理。

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M01/6F/6A/wKioL1WbwHKxdsl-AAJ3jZYOBEA724.jpg" title="選區_009.png" alt="wKioL1WbwHKxdsl-AAJ3jZYOBEA724.jpg" />


本文出自 “牛哥的部落格” 部落格,轉載請與作者聯絡!

從Linux的errno到Java的ThreadLocal

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.