< prev index next >

src/java.base/share/classes/java/lang/ThreadLocal.java

Print this page

 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang;
 27 
 28 import java.lang.ref.WeakReference;
 29 import java.util.Objects;
 30 import java.util.concurrent.atomic.AtomicInteger;
 31 import java.util.function.Supplier;

 32 
 33 import jdk.internal.misc.CarrierThreadLocal;
 34 import jdk.internal.misc.TerminatingThreadLocal;

 35 
 36 /**
 37  * This class provides thread-local variables.  These variables differ from
 38  * their normal counterparts in that each thread that accesses one (via its
 39  * {@code get} or {@code set} method) has its own, independently initialized
 40  * copy of the variable.  {@code ThreadLocal} instances are typically private
 41  * static fields in classes that wish to associate state with a thread (e.g.,
 42  * a user ID or Transaction ID).
 43  *
 44  * <p>For example, the class below generates unique identifiers local to each
 45  * thread.
 46  * A thread's id is assigned the first time it invokes {@code ThreadId.get()}
 47  * and remains unchanged on subsequent calls.
 48  * <pre>
 49  * import java.util.concurrent.atomic.AtomicInteger;
 50  *
 51  * public class ThreadId {
 52  *     // Atomic integer containing the next thread ID to be assigned
 53  *     private static final AtomicInteger nextId = new AtomicInteger(0);
 54  *

 60  *         }
 61  *     };
 62  *
 63  *     // Returns the current thread's unique ID, assigning it if necessary
 64  *     public static int get() {
 65  *         return threadId.get();
 66  *     }
 67  * }
 68  * </pre>
 69  * <p>Each thread holds an implicit reference to its copy of a thread-local
 70  * variable as long as the thread is alive and the {@code ThreadLocal}
 71  * instance is accessible; after a thread goes away, all of its copies of
 72  * thread-local instances are subject to garbage collection (unless other
 73  * references to these copies exist).
 74  * @param <T> the type of the thread local's value
 75  *
 76  * @author  Josh Bloch and Doug Lea
 77  * @since   1.2
 78  */
 79 public class ThreadLocal<T> {


 80     /**
 81      * ThreadLocals rely on per-thread linear-probe hash maps attached
 82      * to each thread (Thread.threadLocals and
 83      * inheritableThreadLocals).  The ThreadLocal objects act as keys,
 84      * searched via threadLocalHashCode.  This is a custom hash code
 85      * (useful only within ThreadLocalMaps) that eliminates collisions
 86      * in the common case where consecutively constructed ThreadLocals
 87      * are used by the same threads, while remaining well-behaved in
 88      * less common cases.
 89      */
 90     private final int threadLocalHashCode = nextHashCode();
 91 
 92     /**
 93      * The next hash code to be given out. Updated atomically. Starts at
 94      * zero.
 95      */
 96     private static AtomicInteger nextHashCode =
 97         new AtomicInteger();
 98 
 99     /**

144      * @return a new thread local variable
145      * @throws NullPointerException if the specified supplier is null
146      * @since 1.8
147      */
148     public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
149         return new SuppliedThreadLocal<>(supplier);
150     }
151 
152     /**
153      * Creates a thread local variable.
154      * @see #withInitial(java.util.function.Supplier)
155      */
156     public ThreadLocal() {
157     }
158 
159     /**
160      * Returns the value in the current thread's copy of this
161      * thread-local variable.  If the variable has no value for the
162      * current thread, it is first initialized to the value returned
163      * by an invocation of the {@link #initialValue} method.
164      * If the current thread does not support thread locals then
165      * this method returns its {@link #initialValue}.
166      *
167      * @return the current thread's value of this thread-local
168      * @see Thread.Builder#allowSetThreadLocals(boolean)
169      */
170     public T get() {
171         return get(Thread.currentThread());
172     }
173 
174     /**
175      * Returns the value in the current carrier thread's copy of this
176      * thread-local variable.
177      */
178     T getCarrierThreadLocal() {
179         assert this instanceof CarrierThreadLocal<T>;
180         return get(Thread.currentCarrierThread());
181     }
182 
183     private T get(Thread t) {
184         ThreadLocalMap map = getMap(t);
185         if (map != null) {
186             if (map == ThreadLocalMap.NOT_SUPPORTED) {
187                 return initialValue();
188             } else {
189                 ThreadLocalMap.Entry e = map.getEntry(this);
190                 if (e != null) {
191                     @SuppressWarnings("unchecked")
192                     T result = (T) e.value;
193                     return result;
194                 }
195             }
196         }
197         return setInitialValue(t);
198     }
199 
200     /**
201      * Returns {@code true} if there is a value in the current carrier thread's copy of
202      * this thread-local variable, even if that values is {@code null}.
203      *
204      * @return {@code true} if current carrier thread has associated value in this
205      *         thread-local variable; {@code false} if not
206      */
207     boolean isCarrierThreadLocalPresent() {
208         assert this instanceof CarrierThreadLocal<T>;
209         return isPresent(Thread.currentCarrierThread());
210     }
211 
212     private boolean isPresent(Thread t) {
213         ThreadLocalMap map = getMap(t);
214         if (map != null && map != ThreadLocalMap.NOT_SUPPORTED) {
215             return map.getEntry(this) != null;
216         } else {
217             return false;
218         }
219     }
220 
221     /**
222      * Variant of set() to establish initialValue. Used instead
223      * of set() in case user has overridden the set() method.
224      *
225      * @return the initial value
226      */
227     private T setInitialValue(Thread t) {
228         T value = initialValue();
229         ThreadLocalMap map = getMap(t);
230         assert map != ThreadLocalMap.NOT_SUPPORTED;
231         if (map != null) {
232             map.set(this, value);
233         } else {
234             createMap(t, value);
235         }
236         if (this instanceof TerminatingThreadLocal<?> ttl) {
237             TerminatingThreadLocal.register(ttl);
238         }



239         return value;
240     }
241 
242     /**
243      * Sets the current thread's copy of this thread-local variable
244      * to the specified value.  Most subclasses will have no need to
245      * override this method, relying solely on the {@link #initialValue}
246      * method to set the values of thread-locals.
247      *
248      * @param value the value to be stored in the current thread's copy of
249      *        this thread-local.
250      *
251      * @throws UnsupportedOperationException if the current thread is not
252      *         allowed to set its copy of thread-local variables
253      *
254      * @see Thread.Builder#allowSetThreadLocals(boolean)
255      */
256     public void set(T value) {
257         set(Thread.currentThread(), value);



258     }
259 
260     void setCarrierThreadLocal(T value) {
261         assert this instanceof CarrierThreadLocal<T>;
262         set(Thread.currentCarrierThread(), value);
263     }
264 
265     private void set(Thread t, T value) {
266         ThreadLocalMap map = getMap(t);
267         if (map == ThreadLocalMap.NOT_SUPPORTED) {
268             throw new UnsupportedOperationException();
269         }
270         if (map != null) {
271             map.set(this, value);
272         } else {
273             createMap(t, value);
274         }
275     }
276 
277     /**
278      * Removes the current thread's value for this thread-local
279      * variable.  If this thread-local variable is subsequently
280      * {@linkplain #get read} by the current thread, its value will be
281      * reinitialized by invoking its {@link #initialValue} method,
282      * unless its value is {@linkplain #set set} by the current thread
283      * in the interim.  This may result in multiple invocations of the
284      * {@code initialValue} method in the current thread.
285      *
286      * @since 1.5
287      */
288      public void remove() {
289          remove(Thread.currentThread());
290      }
291 
292      void removeCarrierThreadLocal() {
293          assert this instanceof CarrierThreadLocal<T>;
294          remove(Thread.currentCarrierThread());
295      }
296 
297      private void remove(Thread t) {
298          ThreadLocalMap m = getMap(t);
299          if (m != null && m != ThreadLocalMap.NOT_SUPPORTED) {
300              m.remove(this);
301          }
302      }
303 
304     /**
305      * Get the map associated with a ThreadLocal. Overridden in
306      * InheritableThreadLocal.
307      *
308      * @param  t the current thread
309      * @return the map
310      */
311     ThreadLocalMap getMap(Thread t) {
312         return t.threadLocals;
313     }
314 
315     /**
316      * Create the map associated with a ThreadLocal. Overridden in
317      * InheritableThreadLocal.
318      *
319      * @param t the current thread

377     static class ThreadLocalMap {
378 
379         /**
380          * The entries in this hash map extend WeakReference, using
381          * its main ref field as the key (which is always a
382          * ThreadLocal object).  Note that null keys (i.e. entry.get()
383          * == null) mean that the key is no longer referenced, so the
384          * entry can be expunged from table.  Such entries are referred to
385          * as "stale entries" in the code that follows.
386          */
387         static class Entry extends WeakReference<ThreadLocal<?>> {
388             /** The value associated with this ThreadLocal. */
389             Object value;
390 
391             Entry(ThreadLocal<?> k, Object v) {
392                 super(k);
393                 value = v;
394             }
395         }
396 
397         // Placeholder when thread locals not supported
398         static final ThreadLocalMap NOT_SUPPORTED = new ThreadLocalMap();
399 
400         /**
401          * The initial capacity -- MUST be a power of two.
402          */
403         private static final int INITIAL_CAPACITY = 16;
404 
405         /**
406          * The table, resized as necessary.
407          * table.length MUST always be a power of two.
408          */
409         private Entry[] table;
410 
411         /**
412          * The number of entries in the table.
413          */
414         private int size = 0;
415 
416         /**
417          * The next size value at which to resize.
418          */
419         private int threshold; // Default to 0

790             }
791 
792             setThreshold(newLen);
793             size = count;
794             table = newTab;
795         }
796 
797         /**
798          * Expunge all stale entries in the table.
799          */
800         private void expungeStaleEntries() {
801             Entry[] tab = table;
802             int len = tab.length;
803             for (int j = 0; j < len; j++) {
804                 Entry e = tab[j];
805                 if (e != null && e.refersTo(null))
806                     expungeStaleEntry(j);
807             }
808         }
809     }







































810 }

 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package java.lang;
 27 
 28 import java.lang.ref.WeakReference;
 29 import java.util.Objects;
 30 import java.util.concurrent.atomic.AtomicInteger;
 31 import java.util.function.Supplier;
 32 import java.util.stream.Collectors;
 33 
 34 import jdk.internal.misc.CarrierThreadLocal;
 35 import jdk.internal.misc.TerminatingThreadLocal;
 36 import sun.security.action.GetPropertyAction;
 37 
 38 /**
 39  * This class provides thread-local variables.  These variables differ from
 40  * their normal counterparts in that each thread that accesses one (via its
 41  * {@code get} or {@code set} method) has its own, independently initialized
 42  * copy of the variable.  {@code ThreadLocal} instances are typically private
 43  * static fields in classes that wish to associate state with a thread (e.g.,
 44  * a user ID or Transaction ID).
 45  *
 46  * <p>For example, the class below generates unique identifiers local to each
 47  * thread.
 48  * A thread's id is assigned the first time it invokes {@code ThreadId.get()}
 49  * and remains unchanged on subsequent calls.
 50  * <pre>
 51  * import java.util.concurrent.atomic.AtomicInteger;
 52  *
 53  * public class ThreadId {
 54  *     // Atomic integer containing the next thread ID to be assigned
 55  *     private static final AtomicInteger nextId = new AtomicInteger(0);
 56  *

 62  *         }
 63  *     };
 64  *
 65  *     // Returns the current thread's unique ID, assigning it if necessary
 66  *     public static int get() {
 67  *         return threadId.get();
 68  *     }
 69  * }
 70  * </pre>
 71  * <p>Each thread holds an implicit reference to its copy of a thread-local
 72  * variable as long as the thread is alive and the {@code ThreadLocal}
 73  * instance is accessible; after a thread goes away, all of its copies of
 74  * thread-local instances are subject to garbage collection (unless other
 75  * references to these copies exist).
 76  * @param <T> the type of the thread local's value
 77  *
 78  * @author  Josh Bloch and Doug Lea
 79  * @since   1.2
 80  */
 81 public class ThreadLocal<T> {
 82     private static final boolean TRACE_VTHREAD_LOCALS = traceVirtualThreadLocals();
 83 
 84     /**
 85      * ThreadLocals rely on per-thread linear-probe hash maps attached
 86      * to each thread (Thread.threadLocals and
 87      * inheritableThreadLocals).  The ThreadLocal objects act as keys,
 88      * searched via threadLocalHashCode.  This is a custom hash code
 89      * (useful only within ThreadLocalMaps) that eliminates collisions
 90      * in the common case where consecutively constructed ThreadLocals
 91      * are used by the same threads, while remaining well-behaved in
 92      * less common cases.
 93      */
 94     private final int threadLocalHashCode = nextHashCode();
 95 
 96     /**
 97      * The next hash code to be given out. Updated atomically. Starts at
 98      * zero.
 99      */
100     private static AtomicInteger nextHashCode =
101         new AtomicInteger();
102 
103     /**

148      * @return a new thread local variable
149      * @throws NullPointerException if the specified supplier is null
150      * @since 1.8
151      */
152     public static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier) {
153         return new SuppliedThreadLocal<>(supplier);
154     }
155 
156     /**
157      * Creates a thread local variable.
158      * @see #withInitial(java.util.function.Supplier)
159      */
160     public ThreadLocal() {
161     }
162 
163     /**
164      * Returns the value in the current thread's copy of this
165      * thread-local variable.  If the variable has no value for the
166      * current thread, it is first initialized to the value returned
167      * by an invocation of the {@link #initialValue} method.


168      *
169      * @return the current thread's value of this thread-local

170      */
171     public T get() {
172         return get(Thread.currentThread());
173     }
174 
175     /**
176      * Returns the value in the current carrier thread's copy of this
177      * thread-local variable.
178      */
179     T getCarrierThreadLocal() {
180         assert this instanceof CarrierThreadLocal<T>;
181         return get(Thread.currentCarrierThread());
182     }
183 
184     private T get(Thread t) {
185         ThreadLocalMap map = getMap(t);
186         if (map != null) {
187             ThreadLocalMap.Entry e = map.getEntry(this);
188             if (e != null) {
189                 @SuppressWarnings("unchecked")
190                 T result = (T) e.value;
191                 return result;




192             }
193         }
194         return setInitialValue(t);
195     }
196 
197     /**
198      * Returns {@code true} if there is a value in the current carrier thread's copy of
199      * this thread-local variable, even if that values is {@code null}.
200      *
201      * @return {@code true} if current carrier thread has associated value in this
202      *         thread-local variable; {@code false} if not
203      */
204     boolean isCarrierThreadLocalPresent() {
205         assert this instanceof CarrierThreadLocal<T>;
206         return isPresent(Thread.currentCarrierThread());
207     }
208 
209     private boolean isPresent(Thread t) {
210         ThreadLocalMap map = getMap(t);
211         if (map != null) {
212             return map.getEntry(this) != null;
213         } else {
214             return false;
215         }
216     }
217 
218     /**
219      * Variant of set() to establish initialValue. Used instead
220      * of set() in case user has overridden the set() method.
221      *
222      * @return the initial value
223      */
224     private T setInitialValue(Thread t) {
225         T value = initialValue();
226         ThreadLocalMap map = getMap(t);

227         if (map != null) {
228             map.set(this, value);
229         } else {
230             createMap(t, value);
231         }
232         if (this instanceof TerminatingThreadLocal<?> ttl) {
233             TerminatingThreadLocal.register(ttl);
234         }
235         if (TRACE_VTHREAD_LOCALS) {
236             dumpStackIfVirtualThread();
237         }
238         return value;
239     }
240 
241     /**
242      * Sets the current thread's copy of this thread-local variable
243      * to the specified value.  Most subclasses will have no need to
244      * override this method, relying solely on the {@link #initialValue}
245      * method to set the values of thread-locals.
246      *
247      * @param value the value to be stored in the current thread's copy of
248      *        this thread-local.





249      */
250     public void set(T value) {
251         set(Thread.currentThread(), value);
252         if (TRACE_VTHREAD_LOCALS) {
253             dumpStackIfVirtualThread();
254         }
255     }
256 
257     void setCarrierThreadLocal(T value) {
258         assert this instanceof CarrierThreadLocal<T>;
259         set(Thread.currentCarrierThread(), value);
260     }
261 
262     private void set(Thread t, T value) {
263         ThreadLocalMap map = getMap(t);



264         if (map != null) {
265             map.set(this, value);
266         } else {
267             createMap(t, value);
268         }
269     }
270 
271     /**
272      * Removes the current thread's value for this thread-local
273      * variable.  If this thread-local variable is subsequently
274      * {@linkplain #get read} by the current thread, its value will be
275      * reinitialized by invoking its {@link #initialValue} method,
276      * unless its value is {@linkplain #set set} by the current thread
277      * in the interim.  This may result in multiple invocations of the
278      * {@code initialValue} method in the current thread.
279      *
280      * @since 1.5
281      */
282      public void remove() {
283          remove(Thread.currentThread());
284      }
285 
286      void removeCarrierThreadLocal() {
287          assert this instanceof CarrierThreadLocal<T>;
288          remove(Thread.currentCarrierThread());
289      }
290 
291      private void remove(Thread t) {
292          ThreadLocalMap m = getMap(t);
293          if (m != null) {
294              m.remove(this);
295          }
296      }
297 
298     /**
299      * Get the map associated with a ThreadLocal. Overridden in
300      * InheritableThreadLocal.
301      *
302      * @param  t the current thread
303      * @return the map
304      */
305     ThreadLocalMap getMap(Thread t) {
306         return t.threadLocals;
307     }
308 
309     /**
310      * Create the map associated with a ThreadLocal. Overridden in
311      * InheritableThreadLocal.
312      *
313      * @param t the current thread

371     static class ThreadLocalMap {
372 
373         /**
374          * The entries in this hash map extend WeakReference, using
375          * its main ref field as the key (which is always a
376          * ThreadLocal object).  Note that null keys (i.e. entry.get()
377          * == null) mean that the key is no longer referenced, so the
378          * entry can be expunged from table.  Such entries are referred to
379          * as "stale entries" in the code that follows.
380          */
381         static class Entry extends WeakReference<ThreadLocal<?>> {
382             /** The value associated with this ThreadLocal. */
383             Object value;
384 
385             Entry(ThreadLocal<?> k, Object v) {
386                 super(k);
387                 value = v;
388             }
389         }
390 



391         /**
392          * The initial capacity -- MUST be a power of two.
393          */
394         private static final int INITIAL_CAPACITY = 16;
395 
396         /**
397          * The table, resized as necessary.
398          * table.length MUST always be a power of two.
399          */
400         private Entry[] table;
401 
402         /**
403          * The number of entries in the table.
404          */
405         private int size = 0;
406 
407         /**
408          * The next size value at which to resize.
409          */
410         private int threshold; // Default to 0

781             }
782 
783             setThreshold(newLen);
784             size = count;
785             table = newTab;
786         }
787 
788         /**
789          * Expunge all stale entries in the table.
790          */
791         private void expungeStaleEntries() {
792             Entry[] tab = table;
793             int len = tab.length;
794             for (int j = 0; j < len; j++) {
795                 Entry e = tab[j];
796                 if (e != null && e.refersTo(null))
797                     expungeStaleEntry(j);
798             }
799         }
800     }
801 
802 
803     /**
804      * Reads the value of the jdk.traceVirtualThreadLocals property to determine if
805      * a stack trace should be printed when a virtual threads sets a thread local.
806      */
807     private static boolean traceVirtualThreadLocals() {
808         String propValue = GetPropertyAction.privilegedGetProperty("jdk.traceVirtualThreadLocals");
809         return (propValue != null)
810                 && (propValue.isEmpty() || Boolean.parseBoolean(propValue));
811     }
812 
813     /**
814      * Print a stack trace if the current thread is a virtual thread.
815      */
816     static void dumpStackIfVirtualThread() {
817         if (Thread.currentThread() instanceof VirtualThread vthread) {
818             try {
819                 var stack = StackWalkerHolder.STACK_WALKER.walk(s ->
820                         s.skip(1)  // skip caller
821                          .collect(Collectors.toList()));
822 
823                 // switch to carrier thread to avoid recursive use of thread-locals
824                 vthread.executeOnCarrierThread(() -> {
825                     System.out.println(vthread);
826                     for (StackWalker.StackFrame frame : stack) {
827                         System.out.format("    %s%n", frame.toStackTraceElement());
828                     }
829                     return null;
830                 });
831             } catch (Exception e) {
832                 throw new InternalError(e);
833             }
834         }
835     }
836 
837     private static class StackWalkerHolder {
838         static final StackWalker STACK_WALKER = StackWalker.getInstance();
839     }
840 }
< prev index next >