日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ThreadLocal如何实现?

發(fā)布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ThreadLocal如何实现? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這是我上周的帖子的后續(xù)文章,在那篇文章中我解釋了ThreadLocal用法的動機 。 從帖子中我們可以回想起,如果您希望每個線程都有一個獨立初始化的變量副本,則ThreadLocal確實是一個很酷的概念。 現(xiàn)在,好奇的人可能已經(jīng)開始問“我如何在Java中實現(xiàn)這樣的概念”?

否則,您可能會覺得這不是一個有趣的話題–畢竟,您在這里所需的只是一張地圖 ,不是嗎? 在處理ThreadLocal <T>時 ,將解決方案實現(xiàn)為HashMap <Thread,T>并以Thread.currentThread()作為鍵似乎是明智的。 其實不是那么簡單。 因此,如果您有五分鐘的時間,請忍受我,我將指導(dǎo)您完成一個美麗的設(shè)計概念。

簡單的HashMap解決方案的第一個明顯問題是線程安全性。 由于HashMap并不是為支持并發(fā)使用而構(gòu)建的,因此我們無法在多線程環(huán)境中安全地使用該實現(xiàn)。 幸運的是,我們不需要花很多時間來解決問題-ConcurrentHashMap <Thread,T>看起來像是天作之合。 檢索的完全并發(fā)性和可調(diào)整的預(yù)期更新并發(fā)性正是我們首先需要的。

現(xiàn)在,如果您將基于ConcurrentHashMap的解決方案應(yīng)用于JDK源代碼中的ThreadLocal實現(xiàn),則會帶來兩個嚴重的問題。

  • 首先,在Map結(jié)構(gòu)中將線程作為鍵。 由于映射永遠不會被垃圾回收,因此最終您將永遠保持對Thread的引用,從而阻止了該線程成為GCd。 不情愿的是,您在設(shè)計中造成了巨大的內(nèi)存泄漏。
  • 第二個問題可能需要更長的時間才能浮出水面,但是即使在幕后進行了巧妙的分段以減少鎖爭用的機會, ConcurrentHashMap仍然承擔(dān)同步開銷。 在同步需求仍然存在的情況下,您仍然擁有一個結(jié)構(gòu),可能成為瓶頸的根源。

但是,讓我們首先開始解決最大的問題。 如果我們的引用是指向相關(guān)線程的最后一個引用,則我們的數(shù)據(jù)結(jié)構(gòu)需要允許對線程進行垃圾回收。 再次,第一個可能的解決方案是盯著我們–而不是通常引用對象,為什么不使用WeakReferences ? 因此,實現(xiàn)現(xiàn)在看起來類似于以下內(nèi)容:

Collections.synchronizedMap(new WeakHashMap<Thread, T>())

現(xiàn)在,我們已經(jīng)解決了泄漏問題–如果除我們之外沒有人引用Thread ,則可以將其定型并進行垃圾回收。 但是我們?nèi)匀粵]有解決并發(fā)問題。 現(xiàn)在,解決方案實際上是關(guān)于跳出思路思考的樣本。 到目前為止,我們已經(jīng)將ThreadLocal變量視為映射到變量的Threads 。 但是,如果我們顛倒了思路,而是設(shè)想了一個解決方案,將ThreadLocal對象映射到每個Thread中的值,該怎么辦? 如果每個線程都存儲該映射,并且ThreadLocal只是該映射的接口,則可以避免同步問題。 更好的是,我們還避免了GC帶來的問題!

確實,當(dāng)我們打開ThreadLocal和Thread類的源代碼時 ,我們看到這正是在JDK中實際實現(xiàn)該解決方案的方式:

public class Thread implements Runnable {ThreadLocal.ThreadLocalMap threadLocals = null;// cut for brevity }public class ThreadLocal<T> {static class ThreadLocalMap {// cut for brevity}ThreadLocalMap getMap(Thread t) {return t.threadLocals;}public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null)return (T) e.value;}return setInitialValue();}private T setInitialValue() {T value = initialValue();Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);return value;}// cut for brevity }

因此,這里有它。 Thread類保留對ThreadLocal.ThreadLocalMap實例的引用,該實例是使用對鍵的弱引用構(gòu)建的。 以相反的方式構(gòu)建結(jié)構(gòu),因為我們的ThreadLocal只能訪問當(dāng)前線程中的值,所以我們完全避免了線程爭用問題。 另外,當(dāng)Thread完成工作時,映射可以進行垃圾回收,因此我們也避免了內(nèi)存泄漏的問題。

希望您對設(shè)計有所了解,因為它確實是解決復(fù)雜問題的理想解決方案。 我確實認為閱讀源代碼是學(xué)習(xí)新概念的理想方式。 而且,如果您是Java開發(fā)人員,那么與閱讀集成到JDK的Joshua Bloch和Doug Lea源代碼相比,還有什么比這更好的獲取知識的地方了?

參考: 如何實現(xiàn)ThreadLocal? 由我們的JCG合作伙伴 Nikita Salnikov Tarnovski在Plumbr Blog博客上獲得。

翻譯自: https://www.javacodegeeks.com/2013/11/how-is-threadlocal-implemented.html

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的ThreadLocal如何实现?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。