摘要:另載于是個很爽的東西,線程安全,能當全局變量來用別。第一家公司,使用框架老技術,現代人可以理解為類似,對每個請求都套上,進入時把寫入,返回或拋注意時清理。第二家公司,某次引入一個設計,也用了來傳遞上下文信息,有的地方沒能清掉。
另載于 http://www.qingjingjie.com/blogs/12
ThreadLocal是個很爽的東西,線程安全,能當全局變量來用(別!)。
上一篇末尾提到ThreadLocal的妙用,這東西確實在框架實現中很常用。不過一定要小心啊。
先告訴大家一個安全秘訣:try-finally大法,百戰百勝!(一定要在finally里清空ThreadLocal)
我職業生涯遇到最棘手的并發bug都是ThreadLocal造成的,稱之為ThreadLocal污染問題。
第一家公司,使用Seam框架(老技術,現代人可以理解為類似Spring MVC),Seam對每個請求都套上Filter,進入時把context寫入ThreadLocal,返回或拋Exception(注意)時清理ThreadLocal。而我們用了很多的庫,有的庫會拋Error,用catch(Exception e)是抓不住的。這就導致有時ThreadLocal沒有被清掉,而服務器用的是線程池,線程會復用啊,那下次請求是不是可能讀到錯誤的context呢?聽起來好嚴重啊!
倒也不會,Seam遇到下一個請求又會把新的context寫入ThreadLocal,覆蓋舊值,就算舊值沒釋放也不要緊。然而!我們的系統有的模塊沒有用Seam,而我們有個內部框架,為了兼容性,會檢測當前線程是否存在Seam context,如果存在,就從context取對象,如果不存在,就另尋蹊徑。有的Filter掛在Seam Filter前面,如果那個Filter調到內部框架,就會先檢測當前線程是否存在Seam context,就讀到上次的context了。
這樣就會出現一些詭異的運行結果,理論上污染會逐漸擴大,直到服務器重啟才恢復。更詭異的是如果被污染的線程下次遇到了Seam Filter,覆蓋舊值,就又恢復正常了,讓人抓不到。
最后當然是診斷并解決了這個問題啦(只能靠推理o(╯□╰)o)。我順便看了Spring MVC的代碼,是用了try-finally大法的,經得起考驗。
第二家公司,某次引入一個設計,也用了ThreadLocal來傳遞上下文信息,有的地方沒能清掉ThreadLocal。于是詭異bug冒出來,百分之一概率出現各種稀奇古怪的運行結果,看不出規律,就是怪。所以大家還是能看到一點規律的——那就是沒有規律!
現在大家應該明白要怎么對待ThreadLocal了吧。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/64533.html
摘要:而應用場景更多是想共享一個變量,但是該變量又不是線程安全的,那么可以用維護一個線程一個實例。因為創建這個對象本身很費時的,而且我們也知道本身不是線程安全的,也不能緩存一個共享的實例,為此我們想到使用來給每個線程緩存一個實例,提高性能。 很多人都知道java中有ThreadLocal這個類,但是知道ThreadLocal這個類具體有什么作用,然后適用什么樣的業務場景還是很少的。今天我就嘗...
摘要:如何在線程池中提交線程內存模型相關問題什么是的內存模型,中各個線程是怎么彼此看到對方的變量的請談談有什么特點,為什么它能保證變量對所有線程的可見性既然能夠保證線程間的變量可見性,是不是就意味著基于變量的運算就是并發安全的請對比下對比的異同。 并發編程高級面試面試題 showImg(https://upload-images.jianshu.io/upload_images/133416...
摘要:缺點每次調用都有線程開銷延遲初始化單例默認構造方法為,避免用戶用構造出新對象獲取單例的靜態工廠同步方法延遲初始化單例使用同步方法保證多線程操作只實例化一個實力單例模式。 主要分為兩種: 直接初始化 延遲初始化 直接初始化 直接初始化final靜態成員 線程安全:JVM保證final靜態成員只會被初始化一次 公有靜態成員是個final域,直接引用成員獲取單例 /** * 公有靜態成...
摘要:方法,刪除當前線程綁定的這個副本數字,這個值是的值,普通的是使用鏈表來處理沖突的,但是是使用線性探測法來處理沖突的,就是每次增加的步長,根據參考資料所說,選擇這個數字是為了讓沖突概率最小。 showImg(https://segmentfault.com/img/remote/1460000019828633); 老套路,先列舉下關于ThreadLocal常見的疑問,希望可以通過這篇學...
摘要:在方法中取出開始時間,并計算耗時。是一個數組主要用來保存具體的數據,是的大小,而這表示當中元素數量超過該值時,就會擴容。如果這個剛好就是當前對象,則直接修改該位置上對象的。 想要獲取更多文章可以訪問我的博客?-?代碼無止境。 什么是ThreadLocal ThreadLocal在《Java核心技術 卷一》中被稱作線程局部變量(PS:關注公眾號itweknow,回復Java核心技術獲取該...
閱讀 1682·2019-08-30 15:54
閱讀 3332·2019-08-26 17:15
閱讀 3522·2019-08-26 13:49
閱讀 2582·2019-08-26 13:38
閱讀 2291·2019-08-26 12:08
閱讀 3035·2019-08-26 10:41
閱讀 1369·2019-08-26 10:24
閱讀 3376·2019-08-23 18:35