感悟:Java的多線程跟Java的類系統之間的關係

一直對Java將線程封裝成對象的技術不甚了了,昨天幫一個新員工定位rosjava使用問題,一開始以爲是多線程問題,但多番嘗試未果後,走查代碼,發現他在onClick函數裏new CustomRosNode並賦給nodeHandler引用,導致nodeHandler最早綁定的對象被GC,問題是CustomRosNode的構造函數並不能構建出一個全功能的node,還需要後續的初始化,但他在onClick只調用了構造函數,導致nodeHandler的publisher指針成了空指針,進而出錯。


但是這個空指針現象讓我首先懷疑Java的線程機制,於是走了很多彎路,找到真正的BUG後,我爲了教育新員工,也爲了回答自己內心的疑惑,在各種關鍵點打印線程ID,發現CustomRosNode有一部分確實運行在子線程(ros的loop),另一部分運行在主線程(構造函數以及其他非ros相關函數),爲何這兩部分代碼能訪問CustomRosNode的同一個數據成員?


晚上睡下後進一步想,爲什麼線程a的代碼可以訪問在線程b中實例化的對象c?答案是:所有Java對象是在【堆】上分配的,而堆是所有線程可見的,只要線程a握有c對象的引用r,則通過r調用c的方法x完全是可行的,只不過這樣一來,方法x就不是運行在線程b上,而是線程a上了!


其實,類(方法和數據)跟線程,一毛錢關係都沒有。可以這麼想象,一個倉庫(堆heap)裏有好多包裹(對象),包裹裏面有商品(數據數據),包裹上面有快遞單指示該怎麼寄送(方法成員),若干個快遞員(線程)負責將這些包裹寄出去,每個快遞員都可以寄任意一個包裹(堆內所有對象都共享同一個4GB進程地址空間),包裹x可以被快遞員a處理,也可以被快遞員b處理,但不能同時被二者處理(synchronized)


Java將所有對象放在堆上,簡化了內存管理,實現了線程類(-_-!引入了混淆),但增加了GC,孰優孰劣?看選擇吧


我選擇go die

發佈了159 篇原創文章 · 獲贊 27 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章