{"id":336,"date":"2011-12-04T20:44:35","date_gmt":"2011-12-04T19:44:35","guid":{"rendered":"http:\/\/doanduyhai.wordpress.com\/?p=336"},"modified":"2011-12-04T20:44:35","modified_gmt":"2011-12-04T19:44:35","slug":"threadlocal-explained","status":"publish","type":"post","link":"https:\/\/www.doanduyhai.com\/blog\/?p=336","title":{"rendered":"ThreadLocal explained"},"content":{"rendered":"<p>Today we are going to look into the ThreadLocal internals, its usage and all the related pitfalls.<\/p>\n<p>ThreadLocal, among other Java advanced features like <strong>volatile<\/strong> variables or <strong>nested<\/strong> classes, is rarely used.<\/p>\n<p>The main reason is its <em>relative<\/em> complexity and mostly the very few cases where ThreadLocal is really required.<\/p>\n<p>Yet, if its underlying mechanism is well understood, ThreadLocal can be very handy in some situations. No wonder it is at the heart of some framework features, Spring<br \/>\n<strong>TransactionSynchronizationManager<\/strong> for example.<br \/>\n<!--more--><br \/>\n&nbsp;<\/p>\n<h1>I Usage<\/h1>\n<h3>A Global design<\/h3>\n<p>ThreadLocal is an alternative to the usage of global variable passed from methods to methods as argument (brute force technique) or static variable (visible within the current ClassLoader).<\/p>\n<p>However, unlike <strong>global<\/strong> or <strong>static<\/strong> variable, <em>the ThreadLocal scope is limited to the execution of the current thread<\/em>, thus its name. A ThreadLocal attached to Thread1 cannot be access by Thread2 and vice versa. This thread isolation makes ThreadLocal <em>thread-safe<\/em> by nature, unlike static variables which need synchronization (thus performance overhead)<\/p>\n<p>A ThreadLocal is composed of the ThreadLocal object itself and a value Object we&#8217;ll refer to as <strong>target Object<\/strong> for the rest of this article.<\/p>\n<p>A ThreadLocal object is created, then attached to the current thread. All portion of your program executed by the current thread can access the ThreadLocal target Object, <strong>provided that the code can access the ThreadLocal reference<\/strong>, and that&#8217;s the trick! There is no point creating a ThreadLocal if it cannot be accessed everywhere in your code.<\/p>\n<p>Most of the time, the ThreadLocal object itself is created as a <strong>static final<\/strong> variable. Static to make it accessible from everywhere and final to avoid being modified. There is no need to synchronize the access to the ThreadLocal object itself since only the target Object is usefull and this object is different from one thread to another (so <em>thread-safe<\/em> by nature)<\/p>\n<h3>B Example<\/h3>\n<pre class=\"brush: java; highlight: [5,29,31]; title: ; wrap-lines: false; notranslate\" title=\"\">\npackage test;\n\npublic class ThreadLocalManager\n{\n\tpublic static final ThreadLocal myThreadLocal = new ThreadLocal();\n}\n\npublic class TestThreadLocal implements Runnable\n{\n\n\tprivate String value;\n\tprivate long delayTime;\n\tprivate long sleepTime;\n\n\tpublic TestThreadLocal(String value, long delayTime, long sleepTime) {\n\t\tthis.value = value;\n\t\tthis.delayTime = delayTime;\n\t\tthis.sleepTime = sleepTime;\n\t}\n\n\t@Override\n\tpublic void run()\n\t{\n\n\t\ttry\n\t\t{\n\t\t\tThread.sleep(this.delayTime);\n\t\t\tSystem.out.println(&amp;quot;[&amp;quot; + this + &amp;quot;] is setting myThreadLocal [&amp;quot; + ThreadLocalManager.myThreadLocal + &amp;quot;] the value : &amp;quot; + this.value);\n\t\t\tThreadLocalManager.myThreadLocal.set(this.value);\n\t\t\tThread.sleep(this.sleepTime);\n\t\t\tSystem.out.println(&amp;quot;[&amp;quot; + this + &amp;quot;] is accessing myThreadLocal [&amp;quot; + ThreadLocalManager.myThreadLocal + &amp;quot;] value : &amp;quot;\n\t\t\t\t\t+ ThreadLocalManager.myThreadLocal.get());\n\t\t}\n\t\tcatch (InterruptedException e)\n\t\t{\n\t\t\te.printStackTrace();\n\t\t}\n\n\t}\n\n\tpublic static void main(String[] args)\n\t{\n\t\tTestThreadLocal test1 = new TestThreadLocal(&amp;quot;V1&amp;quot;, 0, 200);\n\t\tSystem.out.println(&amp;quot;Creating test1 : &amp;quot; + test1);\n\t\tTestThreadLocal test2 = new TestThreadLocal(&amp;quot;V2&amp;quot;, 100, 500);\n\t\tSystem.out.println(&amp;quot;Creating test2 : &amp;quot; + test2);\n\t\tThread t1 = new Thread(test1);\n\t\tThread t2 = new Thread(test2);\n\n\t\tt1.start();\n\t\tt2.start();\n\t}\n\n}\n<\/pre>\n<p>The produced output is:<br \/>\n<code><br \/>\nCreating test1 : test.TestThreadLocal@<strong>30c221<\/strong><br \/>\nCreating test2 : test.TestThreadLocal@<strong>1e5e2c3<\/strong><\/code><\/p>\n<p>[test.TestThreadLocal@<strong>30c221<\/strong>] is setting myThreadLocal [java.lang.ThreadLocal@<strong>f72617<\/strong>] the value : V1<br \/>\n[test.TestThreadLocal@<strong>1e5e2c3<\/strong>] is setting myThreadLocal [java.lang.ThreadLocal@<strong>f72617<\/strong>] the value : V2<br \/>\n[test.TestThreadLocal@<strong>30c221<\/strong>] is accessing myThreadLocal [java.lang.ThreadLocal@<strong>f72617<\/strong>] value : V1<br \/>\n[test.TestThreadLocal@<strong>1e5e2c3<\/strong>] is accessing myThreadLocal [java.lang.ThreadLocal@<strong>f72617<\/strong>] value : V2<\/p>\n<p>Although the execution of both threads is tangled, the output message clearly show that the ThreadLocal value is completely isolated between threads <em>t1<\/em> &amp; <em>t2<\/em>.<br \/>\n&nbsp;<\/p>\n<h1>II Code analysis<\/h1>\n<h3>A Class diagram<\/h3>\n<p>Below is a class diagram of all objects related to ThreadLocal. This diagram has been designed reversing from <strong>openjdk 6-b14<\/strong> source code.<\/p>\n<p><a href=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/threadlocal_class_diagram1.png\"><img loading=\"lazy\" src=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/threadlocal_class_diagram1.png\" alt=\"\" title=\"ThreadLocal_Class_Diagram\" width=\"505\" height=\"345\" class=\"aligncenter size-full wp-image-360\" srcset=\"https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/threadlocal_class_diagram1.png 505w, https:\/\/www.doanduyhai.com\/blog\/wp-content\/uploads\/2011\/12\/threadlocal_class_diagram1-300x205.png 300w\" sizes=\"(max-width: 505px) 100vw, 505px\" \/><\/a><\/p>\n<p><strong>ThreadLocalMap<\/strong> is a static inner class inside <strong>ThreadLocal<\/strong> class<br \/>\n<strong>ThreadLocalMap.Entry<\/strong> is a static inner class inside <strong>ThreadLocalMap<\/strong> class and extending <strong>WeakReference<\/strong> class<\/p>\n<p>A <strong>Thread<\/strong> has a package protected <em>threadLocals<\/em> variable of type <strong>ThreadLocal.ThreadLocalMap<\/strong><br \/>\nA <strong>ThreadLocalMap<\/strong> has a private <em>table<\/em> variable which is an array of <strong>Entry<\/strong> objects<\/p>\n<p>The <strong>ThreadLocal<\/strong> class itself is not extending nor aggregating any above class. Thus it is in relation with <strong>Thread<\/strong> and <strong>ThreadLocalMap<\/strong> classes<\/p>\n<p>The <strong>ThreadLocal<\/strong> class exposes the following methods:<\/p>\n<ul>\n<li><em>get()<\/em>: get the target Object of this ThreadLocal from the current thread. <em>get()<\/em> may return different objects if called withing different threads<\/li>\n<li><em>set(T value)<\/em>: set the target Object of this ThreadLocal to the current thread<\/li>\n<li><em>initialValue()<\/em>: returns the initial target Object of this ThreadLocal. The default implementation returns null. You can make your own ThreadLocal class (extending the default class) returning a non null initial value<\/li>\n<li><em>setInitialValue(T value)<\/em>: set the initial target Object of this ThreadLocal to the current thread. This is merely a call to <em>initialValue()<\/em> followed by a registration of this value into the current thread ThreadLocaLMap<\/li>\n<li><em>createMap(Thread t,T firstValue)<\/em>: initialize a ThreadLocaLMap object for the given thread <em>t<\/em><\/li>\n<li><em>getMap(Thread t)<\/em>: retrieve the ThreadLocaLMap object from the given thread <em>t<\/em><\/li>\n<\/ul>\n<h3>B Source code<\/h3>\n<h5><strong>1) java.lang.Thread<\/strong><\/h5>\n<pre class=\"brush: java; highlight: [4]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic class Thread implements Runnable\n{\n  \u2026\n  ThreadLocal.ThreadLocalMap threadLocals = null;\n  \u2026\n}\n<\/pre>\n<h5><strong>2) java.lang.ThreadLocal<\/strong><\/h5>\n<pre class=\"brush: java; highlight: [5,9,17,29,33,39]; title: ; wrap-lines: false; notranslate\" title=\"\">\npublic class ThreadLocal {\n   \/*********************************** SET CASE *************************\/\n   public void set(T value) {\n        Thread t = Thread.currentThread();\n        ThreadLocalMap map = getMap(t);\n        if (map != null)\n            map.set(this, value);\n        else\n            createMap(t, value);\n   }\n\n   ThreadLocalMap getMap(Thread t) {\n      return t.threadLocals;\n   }\n\n   void createMap(Thread t, T firstValue) {\n        t.threadLocals = new ThreadLocalMap(this, firstValue);\n   }\n\n   \/*********************************** GET CASE *************************\/\n   public T get() {\n        Thread t = Thread.currentThread();\n        ThreadLocalMap map = t.threadLocals;\n        if (map != null) {\n            ThreadLocalMap.Entry e = map.getEntry(this);\n            if (e != null)\n                return (T)e.value;\n        }\n        return setInitialValue();\n   }\n\n   private T setInitialValue() {\n        T value = initialValue();\n        Thread t = Thread.currentThread();\n        ThreadLocalMap map = getMap(t);\n        if (map != null)\n            map.set(this, value);\n        else\n            createMap(t, value);\n        return value;\n   }\n\n   protected T initialValue() {\n        return null;\n   }\n\n   \/*********************************** REMOVE CASE *************************\/\n   public void remove() {\n         ThreadLocalMap m = getMap(Thread.currentThread());\n         if (m != null)\n             m.remove(this);\n   }\n\n   ...\n   ...\n   static class ThreadLocalMap {\n\n      static class Entry extends WeakReference {\n         Object value;\n         Entry(ThreadLocal k, Object v) {\n            super(k);\n            value = v;\n         }\n      }\n\n      private void  set(ThreadLocal key, Object value) {\n\n         Entry[] tab = table;\n         int len = tab.length;\n         int i = key.threadLocalHashCode &amp;amp; (len-1);\n\n         for (Entry e = tab[i];\n            e != null;\n            e = tab[i = nextIndex(i, len)]) {\n\n            ThreadLocal k = e.get();\n            if (k == key) {\n               e.value = value;\n               return;\n            }\n\n            if (k == null) {\n               replaceStaleEntry(key, value, i);\n               return;\n            }\n         }\n\n         tab[i] = new Entry(key, value);\n         ...\n}\n<\/pre>\n<p>The first time <em>set(Object targetObject)<\/em> is called, if the ThreadLocalMap of the current thread does not exist, it is created and then the target Object is set to this map using the ThreadLocal object (<strong>static instance<\/strong>) as search key.<\/p>\n<p>The first time <em>get()<\/em> is called, if the ThreadLocalMap of the current thread exists, the target Object is returned using current ThreadLocal instance as search key. Otherwise a new ThreadLocalMap object is created for current thread and default initial value is set.<\/p>\n<p>As we can see, the static instance of ThreadLocal is used only as <strong>search key<\/strong>. Its value cannot be changed because it is declared <strong>final<\/strong>. The ThreadLocal instance is totally <em>thread-safe<\/em> because it is really <strong>read-only<\/strong> so synchronization is not requited.<\/p>\n<p>What is potentially not thread-safe is the target Object. But since it is put in the ThreadLocalMap of the current thread (package protected access) there is no risk that other threads modify its state.<\/p>\n<p>The <strong>ThreadLocalMap<\/strong> class contains the static inner class Entry, which is just a key-value structure to store the target Object.<\/p>\n<p>What is interesting is the implementation of <em>set(ThreadLocal threadLocal, Object value)<\/em> method of the <strong>ThreadLocalMap<\/strong> class.<\/p>\n<p>Before inserting a new value into the Entry[] table, the table is scanned to check whether the key already exist. If so the old target Object is replaced by the new one.<\/p>\n<p>If one key is null (because garbaged by GC as weak reference), then Entry is considered &#8220;<strong>staled<\/strong>&#8221; and the corresponding target Object is de-referenced. The same Entry instance is re-used to store the current ThreadLocal\/target Object pair.<\/p>\n<p>&nbsp;<\/p>\n<h1>III Memory leak<\/h1>\n<p>The major issue with ThreadLocal is the potential risk of memory leak. Indeed, the ThreadLocalMap contains an array of Entry whose key value extends WeakReference so one can naively think that it will be garbaged by GC automatically when memory is low. <strong>But the fact is that only the key (ThreadLocal object) is a weak reference, not the target object itself !<\/strong><\/p>\n<p>So in case the ThreadLocal object is garbaged, the Entry object still holds a strong reference to the target Object and it is the main source of memory leak.<\/p>\n<p>For sure, the <em>set(ThreadLocal threadLocal, Object value)<\/em> method has a mechanism to detect &#8220;<strong>staled<\/strong>&#8221; objects and remove them but this cleaning process is trigger only by the call to this method.<\/p>\n<p>The best way to avoid memory leak is to call <em>remove()<\/em> method on the ThreadLocal instance once the job is done. This will remove the ThreadLocal key as well as the target Object in the ThreadLocalMap of the current thread.<\/p>\n<p>Calling <em>set(null)<\/em> on the ThreadLocal instance is also fine since it de-reference the target Object but the ThreadLocal object itself will remain in the ThreadLocalMap as key. This is not a big issue since the reference to this ThreadLocal object is a <strong>weak reference<\/strong> as per implementation.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we are going to look into the ThreadLocal internals, its usage and all the related pitfalls. ThreadLocal, among other Java advanced features like volatile variables or nested classes, is rarely used. The main reason is its relative complexity and&#8230;<br \/><a class=\"read-more-button\" href=\"https:\/\/www.doanduyhai.com\/blog\/?p=336\">Read more<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[22,6],"tags":[35],"_links":{"self":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/336"}],"collection":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=336"}],"version-history":[{"count":0,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/336\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=336"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=336"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=336"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}