When should I use a ThreadLocal variable?
How is it used?
One possible (and common) use is when you have some object that is not thread-safe, but you want to avoid synchronizing access to that object (I'm looking at you, SimpleDateFormat). Instead, give each thread its own instance of the object.
For example:
public class Foo
{
// SimpleDateFormat is not thread-safe, so give one to each thread
private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){
#Override
protected SimpleDateFormat initialValue()
{
return new SimpleDateFormat("yyyyMMdd HHmm");
}
};
public String formatIt(Date date)
{
return formatter.get().format(date);
}
}
Documentation.
Since a ThreadLocal is a reference to data within a given Thread, you can end up with classloading leaks when using ThreadLocals in application servers using thread pools. You need to be very careful about cleaning up any ThreadLocals you get() or set() by using the ThreadLocal's remove() method.
If you do not clean up when you're done, any references it holds to classes loaded as part of a deployed webapp will remain in the permanent heap and will never get garbage collected. Redeploying/undeploying the webapp will not clean up each Thread's reference to your webapp's class(es) since the Thread is not something owned by your webapp. Each successive deployment will create a new instance of the class which will never be garbage collected.
You will end up with out of memory exceptions due to java.lang.OutOfMemoryError: PermGen space and after some googling will probably just increase -XX:MaxPermSize instead of fixing the bug.
If you do end up experiencing these problems, you can determine which thread and class is retaining these references by using Eclipse's Memory Analyzer and/or by following Frank Kieviet's guide and followup.
Update: Re-discovered Alex Vasseur's blog entry that helped me track down some ThreadLocal issues I was having.
Many frameworks use ThreadLocals to maintain some context related to the current thread. For example when the current transaction is stored in a ThreadLocal, you don't need to pass it as a parameter through every method call, in case someone down the stack needs access to it. Web applications might store information about the current request and session in a ThreadLocal, so that the application has easy access to them. With Guice you can use ThreadLocals when implementing custom scopes for the injected objects (Guice's default servlet scopes most probably use them as well).
ThreadLocals are one sort of global variables (although slightly less evil because they are restricted to one thread), so you should be careful when using them to avoid unwanted side-effects and memory leaks. Design your APIs so that the ThreadLocal values will always be automatically cleared when they are not needed anymore and that incorrect use of the API won't be possible (for example like this). ThreadLocals can be used to make the code cleaner, and in some rare cases they are the only way to make something work (my current project had two such cases; they are documented here under "Static Fields and Global Variables").
In Java, if you have a datum that can vary per-thread, your choices are to pass that datum around to every method that needs (or may need) it, or to associate the datum with the thread. Passing the datum around everywhere may be workable if all your methods already need to pass around a common "context" variable.
If that's not the case, you may not want to clutter up your method signatures with an additional parameter. In a non-threaded world, you could solve the problem with the Java equivalent of a global variable. In a threaded word, the equivalent of a global variable is a thread-local variable.
There is very good example in book Java Concurrency in Practice. Where author (Joshua Bloch) explains how Thread confinement is one of the simplest ways to achieve thread safety and ThreadLocal is more formal means of maintaining thread confinement. In the end he also explain how people can abuse it by using it as global variables.
I have copied the text from the mentioned book but code 3.10 is missing as it is not much important to understand where ThreadLocal should be use.
Thread-local variables are often used to prevent sharing in designs based on mutable Singletons or global variables. For example, a single-threaded application might maintain a global database connection that is initialized at startup to avoid having to pass a Connection to every method. Since JDBC connections may not be thread-safe, a multithreaded application that uses a global connection without additional coordination is not thread-safe either. By using a ThreadLocal to store the JDBC connection, as in ConnectionHolder in Listing 3.10, each thread will have its own connection.
ThreadLocal is widely used in implementing application frameworks. For example, J2EE containers associate a transaction context with an executing thread for the duration of an EJB call. This is easily implemented using a static Thread-Local holding the transaction context: when framework code needs to determine what transaction is currently running, it fetches the transaction context from this ThreadLocal. This is convenient in that it reduces the need to pass execution context information into every method, but couples any code that uses this mechanism to the framework.
It is easy to abuse ThreadLocal by treating its thread confinement property as a license to use global variables or as a means of creating “hidden” method arguments. Like global variables, thread-local variables can detract from reusability and introduce hidden couplings among classes, and should therefore be used with care.
Essentially, when you need a variable's value to depend on the current thread and it isn't convenient for you to attach the value to the thread in some other way (for example, subclassing thread).
A typical case is where some other framework has created the thread that your code is running in, e.g. a servlet container, or where it just makes more sense to use ThreadLocal because your variable is then "in its logical place" (rather than a variable hanging from a Thread subclass or in some other hash map).
On my web site, I have some further discussion and examples of when to use ThreadLocal that may also be of interest.
Some people advocate using ThreadLocal as a way to attach a "thread ID" to each thread in certain concurrent algorithms where you need a thread number (see e.g. Herlihy & Shavit). In such cases, check that you're really getting a benefit!
ThreadLocal in Java had been introduced on JDK 1.2 but was later generified in JDK 1.5 to introduce type safety on ThreadLocal variable.
ThreadLocal can be associated with Thread scope, all the code which is executed by Thread has access to ThreadLocal variables but two thread can not see each others ThreadLocal variable.
Each thread holds an exclusive copy of ThreadLocal variable which becomes eligible to Garbage collection after thread finished or died, normally or due to any Exception, Given those ThreadLocal variable doesn't have any other live references.
ThreadLocal variables in Java are generally private static fields in Classes and maintain its state inside Thread.
Read more: ThreadLocal in Java - Example Program and Tutorial
The documentation says it very well: "each thread that accesses [a thread-local variable] (via its get or set method) has its own, independently initialized copy of the variable".
You use one when each thread must have its own copy of something. By default, data is shared between threads.
Webapp server may keep a thread pool, and a ThreadLocal var should be removed before response to the client, thus current thread may be reused by next request.
Two use cases where threadlocal variable can be used -
1- When we have a requirement to associate state with a thread (e.g., a user ID or Transaction ID). That usually happens with a web application that every request going to a servlet has a unique transactionID associated with it.
// This class will provide a thread local variable which
// will provide a unique ID for each thread
class ThreadId {
// Atomic integer containing the next thread ID to be assigned
private static final AtomicInteger nextId = new AtomicInteger(0);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId =
ThreadLocal.<Integer>withInitial(()-> {return nextId.getAndIncrement();});
// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
}
Note that here the method withInitial is implemented using lambda expression.
2- Another use case is when we want to have a thread safe instance and we don't want to use synchronization as the performance cost with synchronization is more. One such case is when SimpleDateFormat is used. Since SimpleDateFormat is not thread safe so we have to provide mechanism to make it thread safe.
public class ThreadLocalDemo1 implements Runnable {
// threadlocal variable is created
private static final ThreadLocal<SimpleDateFormat> dateFormat = new ThreadLocal<SimpleDateFormat>(){
#Override
protected SimpleDateFormat initialValue(){
System.out.println("Initializing SimpleDateFormat for - " + Thread.currentThread().getName() );
return new SimpleDateFormat("dd/MM/yyyy");
}
};
public static void main(String[] args) {
ThreadLocalDemo1 td = new ThreadLocalDemo1();
// Two threads are created
Thread t1 = new Thread(td, "Thread-1");
Thread t2 = new Thread(td, "Thread-2");
t1.start();
t2.start();
}
#Override
public void run() {
System.out.println("Thread run execution started for " + Thread.currentThread().getName());
System.out.println("Date formatter pattern is " + dateFormat.get().toPattern());
System.out.println("Formatted date is " + dateFormat.get().format(new Date()));
}
}
Since Java 8 release, there is more declarative way to initialize ThreadLocal:
ThreadLocal<String> local = ThreadLocal.withInitial(() -> "init value");
Until Java 8 release you had to do the following:
ThreadLocal<String> local = new ThreadLocal<String>(){
#Override
protected String initialValue() {
return "init value";
}
};
Moreover, if instantiation method (constructor, factory method) of class that is used for ThreadLocal does not take any parameters, you can simply use method references (introduced in Java 8):
class NotThreadSafe {
// no parameters
public NotThreadSafe(){}
}
ThreadLocal<NotThreadSafe> container = ThreadLocal.withInitial(NotThreadSafe::new);
Note:
Evaluation is lazy since you are passing java.util.function.Supplier lambda that is evaluated only when ThreadLocal#get is called but value was not previously evaluated.
You have to be very careful with the ThreadLocal pattern. There are some major down sides like Phil mentioned, but one that wasn't mentioned is to make sure that the code that sets up the ThreadLocal context isn't "re-entrant."
Bad things can happen when the code that sets the information gets run a second or third time because information on your thread can start to mutate when you didn't expect it. So take care to make sure the ThreadLocal information hasn't been set before you set it again.
ThreadLocal will ensure accessing the mutable object by the multiple
threads in the non synchronized method is synchronized, means making
the mutable object to be immutable within the method. This
is achieved by giving new instance of mutable object for each thread
try accessing it. So It is local copy to the each thread. This is some
hack on making instance variable in a method to be accessed like a
local variable. As you aware method local variable is only available
to the thread, one difference is; method local variables will not
available to the thread once method execution is over where as mutable
object shared with threadlocal will be available across multiple
methods till we clean it up.
By Definition:
The ThreadLocal class in Java enables you to create variables that can
only be read and written by the same thread. Thus, even if two threads
are executing the same code, and the code has a reference to a
ThreadLocal variable, then the two threads cannot see each other's
ThreadLocal variables.
Each Thread in java contains ThreadLocalMap in it.
Where
Key = One ThreadLocal object shared across threads.
value = Mutable object which has to be used synchronously, this will be instantiated for each thread.
Achieving the ThreadLocal:
Now create a wrapper class for ThreadLocal which is going to hold the mutable object like below (with or without initialValue()). Now getter and setter of this wrapper will work on threadlocal instance instead of mutable object.
If getter() of threadlocal didn't find any value with in the threadlocalmap of the Thread; then it will invoke the initialValue() to get its private copy with respect to the thread.
class SimpleDateFormatInstancePerThread {
private static final ThreadLocal<SimpleDateFormat> dateFormatHolder = new ThreadLocal<SimpleDateFormat>() {
#Override
protected SimpleDateFormat initialValue() {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd") {
UUID id = UUID.randomUUID();
#Override
public String toString() {
return id.toString();
};
};
System.out.println("Creating SimpleDateFormat instance " + dateFormat +" for Thread : " + Thread.currentThread().getName());
return dateFormat;
}
};
/*
* Every time there is a call for DateFormat, ThreadLocal will return calling
* Thread's copy of SimpleDateFormat
*/
public static DateFormat getDateFormatter() {
return dateFormatHolder.get();
}
public static void cleanup() {
dateFormatHolder.remove();
}
}
Now wrapper.getDateFormatter() will call threadlocal.get() and that will check the currentThread.threadLocalMap contains this (threadlocal) instance.
If yes return the value (SimpleDateFormat) for corresponding threadlocal instance
else add the map with this threadlocal instance, initialValue().
Herewith thread safety achieved on this mutable class; by each thread is working with its own mutable instance but with same ThreadLocal instance. Means All the thread will share the same ThreadLocal instance as key, but different SimpleDateFormat instance as value.
https://github.com/skanagavelu/yt.tech/blob/master/src/ThreadLocalTest.java
when?
When an object is not thread-safe, instead of synchronization which hampers the scalability, give one object to every thread and keep it thread scope, which is ThreadLocal. One of most often used but not thread-safe objects are database Connection and JMSConnection.
How ?
One example is Spring framework uses ThreadLocal heavily for managing transactions behind the scenes by keeping these connection objects in ThreadLocal variables. At high level, when a transaction is started it gets the connection ( and disables the auto commit ) and keeps it in ThreadLocal. on further db calls it uses same connection to communicate with db. At the end, it takes the connection from ThreadLocal and commits ( or rollback ) the transaction and releases the connection.
I think log4j also uses ThreadLocal for maintaining MDC.
ThreadLocal is useful, when you want to have some state that should not be shared amongst different threads, but it should be accessible from each thread during its whole lifetime.
As an example, imagine a web application, where each request is served by a different thread. Imagine that for each request you need a piece of data multiple times, which is quite expensive to compute. However, that data might have changed for each incoming request, which means that you can't use a plain cache. A simple, quick solution to this problem would be to have a ThreadLocal variable holding access to this data, so that you have to calculate it only once for each request. Of course, this problem can also be solved without the use of ThreadLocal, but I devised it for illustration purposes.
That said, have in mind that ThreadLocals are essentially a form of global state. As a result, it has many other implications and should be used only after considering all the other possible solutions.
There are 3 scenarios for using a class helper like SimpleDateFormat in multithread code, which best one is use ThreadLocal
Scenarios
1- Using like share object by the help of lock or synchronization mechanism which makes the app slow
Thread pool Scenarios
2- Using as a local object inside a method
In thread pool, in this scenario, if we have 4 thread each one has 1000 task time then we have
4000 SimpleDateFormat object created and waiting for GC to erase them
3- Using ThreadLocal
In thread pool, if we have 4 thread and we gave to each thread one SimpleDateFormat instance
so we have 4 threads, 4 objects of SimpleDateFormat.
There is no need of lock mechanism and object creation and destruction. (Good time complexity and space complexity)
https://www.youtube.com/watch?v=sjMe9aecW_A
Nothing really new here, but I discovered today that ThreadLocal is very useful when using Bean Validation in a web application. Validation messages are localized, but by default use Locale.getDefault(). You can configure the Validator with a different MessageInterpolator, but there's no way to specify the Locale when you call validate. So you could create a static ThreadLocal<Locale> (or better yet, a general container with other things you might need to be ThreadLocal and then have your custom MessageInterpolator pick the Locale from that. Next step is to write a ServletFilter which uses a session value or request.getLocale() to pick the locale and store it in your ThreadLocal reference.
As was mentioned by #unknown (google), it's usage is to define a global variable in which the value referenced can be unique in each thread. It's usages typically entails storing some sort of contextual information that is linked to the current thread of execution.
We use it in a Java EE environment to pass user identity to classes that are not Java EE aware (don't have access to HttpSession, or the EJB SessionContext). This way the code, which makes usage of identity for security based operations, can access the identity from anywhere, without having to explicitly pass it in every method call.
The request/response cycle of operations in most Java EE calls makes this type of usage easy since it gives well defined entry and exit points to set and unset the ThreadLocal.
Thread-local variables are often used to prevent sharing in designs based on
mutable Singletons or global variables.
It can be used in scenarios like making seperate JDBC connection for each thread when you are not using a Connection Pool.
private static ThreadLocal<Connection> connectionHolder
= new ThreadLocal<Connection>() {
public Connection initialValue() {
return DriverManager.getConnection(DB_URL);
}
};
public static Connection getConnection() {
return connectionHolder.get();
}
When you call getConnection, it will return a connection associated with that thread.The same can be done with other properties like dateformat, transaction context that you don't want to share between threads.
You could have also used local variables for the same, but these resource usually take up time in creation,so you don't want to create them again and again whenever you perform some business logic with them. However, ThreadLocal values are stored in the thread object itself and as soon as the thread is garbage collected, these values are gone too.
This link explains use of ThreadLocal very well.
Caching, sometime you have to calculate the same value lots of time so by storing the last set of inputs to a method and the result you can speed the code up. By using Thread Local Storage you avoid having to think about locking.
ThreadLocal is a specially provisioned functionality by JVM to provide an isolated storage space for threads only. like the value of instance scoped variable are bound to a given instance of a class only. each object has its only values and they can not see each other value. so is the concept of ThreadLocal variables, they are local to the thread in the sense of object instances other thread except for the one which created it, can not see it. See Here
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;
public class ThreadId {
private static final AtomicInteger nextId = new AtomicInteger(1000);
// Thread local variable containing each thread's ID
private static final ThreadLocal<Integer> threadId = ThreadLocal.withInitial(() -> nextId.getAndIncrement());
// Returns the current thread's unique ID, assigning it if necessary
public static int get() {
return threadId.get();
}
public static void main(String[] args) {
new Thread(() -> IntStream.range(1, 3).forEach(i -> {
System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
})).start();
new Thread(() -> IntStream.range(1, 3).forEach(i -> {
System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
})).start();
new Thread(() -> IntStream.range(1, 3).forEach(i -> {
System.out.println(Thread.currentThread().getName() + " >> " + new ThreadId().get());
})).start();
}
}
The ThreadLocal class in Java enables you to create variables that can only be read and written by the same thread. Thus, even if two threads are executing the same code, and the code has a reference to a ThreadLocal variable, then the two threads cannot see each other's ThreadLocal variables.
Read more
[For Reference]ThreadLocal cannot solve update problems of shared object. It is recommended to use a staticThreadLocal object which is shared by all operations in the same thread.
[Mandatory]remove() method must be implemented by ThreadLocal variables, especially when using thread pools in which threads are often reused. Otherwise, it may affect subsequent business logic and cause unexpected problems such as memory leak.
Threadlocal provides a very easy way to achieve objects reusability with zero cost.
I had a situation where multiple threads were creating an image of mutable cache, on each update notification.
I used a Threadlocal on each thread, and then each thread would just need to reset old image and then update it again from the cache on each update notification.
Usual reusable objects from object pools have thread safety cost associated with them, while this approach has none.
Try this small example, to get a feel for ThreadLocal variable:
public class Book implements Runnable {
private static final ThreadLocal<List<String>> WORDS = ThreadLocal.withInitial(ArrayList::new);
private final String bookName; // It is also the thread's name
private final List<String> words;
public Book(String bookName, List<String> words) {
this.bookName = bookName;
this.words = Collections.unmodifiableList(words);
}
public void run() {
WORDS.get().addAll(words);
System.out.printf("Result %s: '%s'.%n", bookName, String.join(", ", WORDS.get()));
}
public static void main(String[] args) {
Thread t1 = new Thread(new Book("BookA", Arrays.asList("wordA1", "wordA2", "wordA3")));
Thread t2 = new Thread(new Book("BookB", Arrays.asList("wordB1", "wordB2")));
t1.start();
t2.start();
}
}
Console output, if thread BookA is done first:
Result BookA: 'wordA1, wordA2, wordA3'.
Result BookB: 'wordB1, wordB2'.
Console output, if thread BookB is done first:
Result BookB: 'wordB1, wordB2'.
Result BookA: 'wordA1, wordA2, wordA3'.
1st Use case - Per thread context which gives thread safety as well as performance
Real-time example in SpringFramework classes -
LocaleContextHolder
TransactionContextHolder
RequestContextHolder
DateTimeContextHolder
2nd Use case - When we don't want to share something among threads and at the same time don't want to use synchronize/lock due to performance cost
example - SimpleDateFormat to create the custom format for dates
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* #author - GreenLearner(https://www.youtube.com/c/greenlearner)
*/
public class ThreadLocalDemo1 {
SimpleDateFormat sdf = new SimpleDateFormat("dd-mm-yyyy");//not thread safe
ThreadLocal<SimpleDateFormat> tdl1 = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-dd-mm"));
public static void main(String[] args) {
ThreadLocalDemo1 d1 = new ThreadLocalDemo1();
ExecutorService es = Executors.newFixedThreadPool(10);
for(int i=0; i<100; i++) {
es.submit(() -> System.out.println(d1.getDate(new Date())));
}
es.shutdown();
}
String getDate(Date date){
// String s = tsdf.get().format(date);
String s1 = tdl1.get().format(date);
return s1;
}
}
Usage Tips
Use local variables if possible. This way we can avoid using ThreadLocal
Delegate the functionality to frameworks as and when possible
If using ThreadLocal and setting the state into it then make sure to clean it after using otherwise it can become the major reason for OutOfMemoryError
Related
I have following use-case:
Need a single background thread which maintains a set of accountIDs in memory and it fetches the latest accountIds every 1 second
Other multiple parallel running process will search if particular accountID is present in above Set or not
To achieve above use-case, I have following code. runTask() is a method which is responsible for fetching new Set every 1 second. doesAccountExist method is called by other parallel threads to check if accountId exists in the Set or not.
class AccountIDFetcher {
private Set<String> accountIds;
private ScheduledExecutorService scheduledExecutorService;
public AccountIDFetcher() {
this.accountIds = new HashSet<String>();
scheduledThreadPoolExecutor = new ScheduledThreadPoolExecutor(1);
scheduledExecutorService.scheduleWithFixedDelay(this::runTask, 0, 1, TimeUnit.SECONDS);
}
// Following method runs every 1 second
private void runTask() {
accountIds = getAccountIds()
}
// other parallel thread calls below method
public boolean doesAccountExist(String accountId) {
return accountIds.contains(instanceId);
}
private Set<String> getAccountIds() {
Set<String> accounts = new HashSet<String>();
// calls Database and put list of accountIds into above set
return accounts;
}
}
I have following question
In runTask method, I just change the reference of accountIds variable to a new object. So if, Thread-2 is in the middle of searching accountId in doesAccountExist() method and at the same time if Thread-1 executes runTask() & changes the reference of accountIds variable to a new object then old object gets orphaned. is it possible that old object can be garbage collected before Thread-2 finish searching in it?
tl;dr
You asked:
is it possible that old object can be garbage collected before Thread-2 finish searching in it?
No, the old Set object does not become garbage while some thread is still using it.
An object only becomes a candidate for garbage-collection after each and every reference to said object (a) goes out of scope, (b) is set to null, or (c) is a weak reference.
No, an object in use within a method will not be garbage-collected
In Java, an object reference assignment is atomic, as discussed in another Question. When this.accountIds is directed to point to a new Set object, that happens in one logical operation. That means that any other code in any other thread accessing the accountIds member field will always successfully access either the old Set object or the new Set object, always one or the other.
If during that re-assignment another thread accessed the old Set object, that other thread's code is working with a copy of the object reference. You can think of your doesAccountExist method:
public boolean doesAccountExist(String accountId) {
return accountIds.contains(accountId);
}
…as having a local variable with a copy of the object reference, as if written like this:
public boolean doesAccountExist(String accountId) {
Set<String> set = this.accountIds ;
return set.contains(accountId);
}
While one thread is replacing the reference to a new Set on the member field accountIds, the doesAccountExist method already has a copy of the reference to the old Set. At that moment, while one thread is changing the member field reference, and another thread has a local reference, the garbage collector sees both the new and old Set objects as having (at least) one reference each. So neither is a candidate for being garbage-collected.
Actually, more technically correct would be explaining that at the point in your line return accountIds.contains(accountId); where execution reaches the accountIds portion, the current (old) Set will be accessed. A moment later the contains method begins its work, during which re-assigning a new Set to that member field has no effect on this method's work-in-progress already using the old Set.
This means that even after the new Set has been assigned in one thread, the other thread may still be continuing its work of searching the old Set. This may or may not be a problem depending on the business context of your app. But your Question did not address this stale-data transactional aspect.
So regarding your question:
is it possible that old object can be garbage collected before Thread-2 finish searching in it?
No, the old Set object does not become garbage while some thread is still using it.
Other issues
Your code does have other issues.
Visibility
You declared your member field as private Set<String> accountIds;. If you access that member field across threads on a host machine with multiple cores, then you have a visibility problem. The caches on each core may not be refreshed immediately when you assign a different object to that member field. As currently written, it is entirely possible that one thread accessing this.accountIds will gain access to the old Set object even after that variable was assigned the new Set object.
If you do not already know about the issues I mention, study up on concurrency. There is more involved than I can cover here. Learn about the Java Memory Model. And I strongly recommend reading and re-reading the classic book, Java Concurrency in Practice by Brian Goetz, et al.
volatile
One solution is to mark the member field as volatile. So, this:
private Set<String> accountIds;
…becomes this:
volatile private Set<String> accountIds;
Marking as volatile avoids a stale cache on a CPU core pointing to the old object reference rather than the new object reference.
AtomicReference
Another solution is using an object of AtomicReference class as the member field. I would mark it final so that one and only one such object is ever assigned to that member field, so the field is a constant rather than a variable. Then assign each new Set object as the payload contained within that AtomicReference object. Code wanting the current Set object calls a getter method on that AtomicReference object. This call is guaranteed to be thread-safe, eliminating the need for volatile.
Concurrent access to existing Set
Another possible problem with your code might be concurrent access to an existing Set. If you have more than one thread accessing the existing Set, then you must protect that resource.
One way to protect access to that Set is to use a thread-safe implementation of Set such as ConcurrentSkipListSet.
From what you have showed in the Question, the only access to the existing Set that I noticed is calling contains. If you are never modifying the existing Set, then merely calling contains across multiple threads may be safe — I just don't know, you'd have to research it.
If you intend to never modify an existing Set, then you can enforce that by using an unmodifiable set. One way to produce an unmodifiable set is to construct and populate a regular set. Then feed that regular set to the method Set.copyOf. So your getAccountIds method would look like this:
private Set<String> getAccountIds() {
Set<String> accounts = new HashSet<String>();
// calls Database and put list of accountIds into above set
return Set.copyOf( accounts );
}
Return a copy rather a reference
There are two easy ways to avoid dealing with concurrency:
Make the object immutable
Provide a copy of the object
As for the first way, immutability, the Java Collections Framework is generally very good but unfortunately lacks explicit mutability & immutability in its type system. The Set.of methods and Collections.unmodifiableSet both provide a Set that cannot be modified. But the type itself does not proclaim that fact. So we cannot ask the compiler to enforce a rule such as our AtomicReference only storing an immutable set. As an alternative, consider using a third-party collections with immutability as part of its type. Perhaps Eclipse Collections or Google Guava.
As for the second way, we can make a copy of our Set of account IDs whenever needing access. So we need a getCurrentAccountIds method that goes into the AtomicReference, retrieves the Set stored there, and called Set.copyOf to produce a new set of the same contained objects. This copy operation is not documented as being thread-safe. So we should mark the method synchronized to allow only one copy operation at a time. Bonus: We can mark this method public to give any calling programmer access to the Set of account IDs for their own perusal.
synchronized public Set < UUID > getCurrentAccountIds ( )
{
return Set.copyOf( this.accountIdsRef.get() ); // Safest approach is to return a copy rather than original set.
}
Our convenience method doesAccountExist should call that same getCurrentAccountIds to obtain a copy of the set before doing its "contains" logic. This way we do not care whether or not the "contains" work is thread-safe.
Caveat: I am not satisfied with using Set.copyOf to as means to avoid any possible thread-safety issues. That method notes that if the passed collection being copied is already an unmodifiable set, then a copy may not be made. In real work I would use a Set implementation that guarantees thread-safety whether found bundled with Java or by adding a third-party library.
Do not use object within constructor
I do not like seeing the scheduled executor service appearing within your constructor. I see two issues there: (a) app lifecycle and (b) using an object within a constructor.
Creating the executor service, scheduling tasks on that service, and shutting down that service are all related to the lifecycle of the app. An object generally should not be aware of its lifecycle within the greater app. This account IDs provider object should know only how to do its job (provide IDs) but should not be responsible for putting itself to work. So your code is mixing responsibilities, which is generally a poor practice.
Another problem is that the executor service is being scheduled to immediately start using the very object that we are still constructing. Generally, the best practice is to not use an object while still under construction. You may get away with such use, but doing so is risky and is prone to leading to bugs. A constructor should be short and sweet, used just to validate inputs, establish required resources, and ensure the integrity of the object being birthed.
I did not pull the service out of your constructor only because I did not want to this Answer to go too far out into the weeds. However, I did make two adjustments. (a) I changed the initial delay on the scheduleWithFixedDelay call from zero to one second. This is a hack to give the constructor time to finish birthing the object before its first use. (b) I added the tearDown method to properly shutdown the executor service so its backing thread-pool does not continue running indefinitely in zombie fashion.
Tips
I suggest renaming your getAccountIds() method. The get wording in Java is usually associated with the JavaBeans convention of accessing an existing property. In your case you are generating an entirely new replacement set of values. So I would change that name to something like fetchFreshAccountIds.
Consider wrapping your scheduled task with a try-catch. Any Exception or Error bubbling up to reach the ScheduledExecutorService brings a silent halt to any further scheduling. See ScheduledExecutorService Exception handling.
Example code.
Here is a complete example of my take on your code.
Caveat: Use at your own risk. I am not a concurrency expert. This is meant as food-for-thought, not production use.
I used UUID as the data type of the account IDs to be more realistic and clear.
I changed some of your class & method names for clarity.
Notice which methods are private and which are public.
package work.basil.example;
import java.time.Duration;
import java.time.Instant;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
public class AccountIdsProvider
{
// Member fields
private AtomicReference < Set < UUID > > accountIdsRef;
private ScheduledExecutorService scheduledExecutorService;
// Constructor
public AccountIdsProvider ( )
{
this.accountIdsRef = new AtomicReference <>();
this.accountIdsRef.set( Set.of() ); // Initialize to empty set.
this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
scheduledExecutorService.scheduleWithFixedDelay( this :: replaceAccountIds , 1 , 1 , TimeUnit.SECONDS ); // I strongly suggest you move the executor service and the scheduling work to be outside this class, to be a different class’ responsibility.
}
// Performs database query to find currently relevant account IDs.
private void replaceAccountIds ( )
{
// Beware: Any uncaught Exception or Error bubbling up to the scheduled executor services halts the scheduler immediately and silently.
try
{
System.out.println( "Running replaceAccountIds. " + Instant.now() );
Set < UUID > freshAccountIds = this.fetchFreshAccountIds();
this.accountIdsRef.set( freshAccountIds );
System.out.println( "freshAccountIds = " + freshAccountIds + " at " + Instant.now() );
}
catch ( Throwable t )
{
t.printStackTrace();
}
}
// Task to be run by scheduled executor service.
private Set < UUID > fetchFreshAccountIds ( )
{
int limit = ThreadLocalRandom.current().nextInt( 0 , 4 );
HashSet < UUID > uuids = new HashSet <>();
for ( int i = 1 ; i <= limit ; i++ )
{
uuids.add( UUID.randomUUID() );
}
return Set.copyOf( uuids ); // Return unmodifiable set.
}
// Calling programmers can get a copy of the set of account IDs for their own perusal.
// Pass a copy rather than a reference for thread-safety.
// Synchronized in case copying the set is not thread-safe.
synchronized public Set < UUID > getCurrentAccountIds ( )
{
return Set.copyOf( this.accountIdsRef.get() ); // Safest approach is to return a copy rather than original set.
}
// Convenience method for calling programmers.
public boolean doesAccountExist ( UUID accountId )
{
return this.getCurrentAccountIds().contains( accountId );
}
// Destructor
public void tearDown ( )
{
// IMPORTANT: Always shut down your executor service. Otherwise the backing pool of threads may run indefinitely, like a zombie 🧟.
if ( Objects.nonNull( this.scheduledExecutorService ) )
{
System.out.println( "INFO - Shutting down the scheduled executor service. " + Instant.now() );
this.scheduledExecutorService.shutdown(); // I strongly suggest you move the executor service and the scheduling work to be outside this class, to be a different class’ responsibility.
}
}
public static void main ( String[] args )
{
System.out.println( "INFO - Starting app. " + Instant.now() );
AccountIdsProvider app = new AccountIdsProvider();
try { Thread.sleep( Duration.ofSeconds( 10 ).toMillis() ); } catch ( InterruptedException e ) { e.printStackTrace(); }
app.tearDown();
System.out.println( "INFO - Ending app. " + Instant.now() );
}
}
Garbage collection is not the main issue with this code. The lack of any synchronization is the main issue.
If thread-2 is "searching" in something, it necessarily has a reference to that thing, so it's not going to get GC'd.
Why not use 'synchronized' so you can be sure of what will happen?
garbage collection wise, you will not get into any surprise, but not because the accepted answer implies. It is somehow more tricky.
May be visualizing this will help.
accountIds ----> some_instance_1
Suppose ThreadA is now working with some_instance_1. It started to search for accountId in it. While that operation is going, ThreadB changes what that reference is pointing to. So it becomes:
some_instance_1
accountIds ----> some_instance_2
Because reference assign is atomic, this is what ThreadA will see also, if it reads that reference again. At this point in time, some_instance_1 is eligible for garbage collection, since no one refers to it. Just take note, that this will only happen if ThreadA sees this write that ThreadB did. Either way : you are safe (gc wise only), because ThreadA either works with a stale copy (which you said it's OK) or the most recent one.
This does not mean that everything is fine with your code.
What that answer gets right indeed is that reference assigning is atomic, so once a thread writes to a reference (accountIds = getAccountIds()), a reading thread (accountIds.contains(instanceId);) that will indeed perform the read will see the write. I say "indeed" because an optimizer might not even issue such a read, to begin with. In very simple (and somehow wrong) words, each thread might get its own copy of accountIds and because that is a "plain" read without any special semantics (like volatile, release/acquire, synchronization, etc), reading threads have no obligation to see the writing thread action.
So, even if someone actually did accountIds = getAccountIds(), it does not mean that reading threads will see this. And it gets worse. This write might not ever be seen. You need to introduce special semantics if you want guarantees (and you absolutely do).
For that you need to make your Set volatile:
private volatile Set<String> accountIds = ...
so that when multi threads are involved, you would get the needed visibility guarantees.
Then not to interfere with any in-flight updates of accountIds, you can simply work on a local copy of it:
public boolean doesAccountExist(String accountId) {
Set<String> local = accountIds;
return local.contains(accountId);
}
Even if accountIds change while you are in this method, you do not care about that change, since you are searching against local, which is unaware of the change.
public class VPattern implements Pattern
{
private final TokenKey tokenKey_;
private final String tokenLabel_;
private Integer cachedHashCode_ = null;
private ThreadLocal<Token> token_ = new ThreadLocal<Token>();
...
}
I am reading this piece of code and don't understand the use of ThreadLocal here. Is that because ThreadLocal is used to ensure the 'token_' object will be thread safe in any concurrent situation? If that's the case, why TokenKey and Integer are not thread safety protected? I know that "String" is always thread safe.
Every thread gets its own Token even if they share the same instance of VPattern. Possibly this was done because Token is not thread safe and VPattern wants to avoid synchronizing access to the Token instance. tokenKey_ is final so don't have to worry about the field changing, and maybe it's thread safe on its own. tokenLabel_ is also final and strings are immutable so no issue there. cachedHashCode_ is the odd one out here; is access to it protected somehow? It's hard to say what's going on without seeing the rest of the class.
In general, ThreadLocal can provide different objects for each working thread. So if the given object is not thread-safe nor singleton, it can be stored in ThreadLocal variable. Then every thread may get and safely use different instance of your class. You can treat it like a map, where the current thread is a key and the actual object is a value.
Let's assume there are two threads working at the same time and sharing one VPattern object. If threads get tokenKey_ or tokenLabel_, then both will get the same instances. But if both threads call token.get(), then they will get different instances of Token type (if initialized previously, see: set method and withInitial static factory method).
Unfortunately it's hard to say what's the purpose of ThreadLocal in your case because it highly depends on the context. Seems that Token objects cannot be shared by different threads (each thread should have own token).
You can read more about ThreadLocal in javadoc or here: https://www.baeldung.com/java-threadlocal
I was reading Effective Java, and came across a condition where Joshua Bloch recommends something like
class MyComparator extends Comparator<String>{
private MyComparator(){}
private static final MyComparator INSTANCE = new MyComparator();
public int compare(String s1,String s2){
// Omitted
}
}
XYZComparator is stateless, it has no fields. hence all instances of the class are functionally equivalent. Thus it should be a singleton to save on unnecessary object creation.
So is it always safe to create a static final Object of whatever class it is pointing to if it has no fields? Wouldn't this cause multithreading issue when compare is called from two threads parallely? Or I misunderstood something basic. Is it like every thread has autonomy of execution if no fields is shared?
So is it always safe to create a static final Object of whatever class it is pointing to if it has no fields?
I would dare to say yes. Having no fields makes a class stateless and, thus, immutable, which is always desirable in a multithreading environment.
Stateless objects are always thread-safe.
Immutable objects are always thread-safe.
An excerpt from Java Concurrency In Practice:
Since the actions of a thread accessing a stateless object cannot affect the correctness of operations in other threads, stateless objects are thread-safe.
Stateless objects are always thread-safe.
The fact that most servlets can be implemented with no state greatly reduces the burden of making servlets threadͲ
safe. It is only when servlets want to remember things from one request to another that the thread-safety requirement becomes an issue.
...
An immutable object is one whose state cannot be changed after construction. Immutable objects are inherently
thread-safe; their invariants are established by the constructor, and if their state cannot be changed, these invariants
always hold.
Immutable objects are always thread-safe.
Immutable objects are simple. They can only be in one state, which is carefully controlled by the constructor. One of the
most difficult elements of program design is reasoning about the possible states of complex objects. Reasoning about
the state of immutable objects, on the other hand, is trivial.
Wouldn't this cause multithreading issue when compare is called from two threads parallelly?
No. Each thread has own stack where local variables (including method parameters) are stored. The thread's stack isn't shared, so there is no way to mess it up parallelly.
Another good example would be a stateless servlet. One more extract from that great book.
#ThreadSafe
public class StatelessFactorizer implements Servlet {
public void service(ServletRequest req, ServletResponse resp) {
BigInteger i = extractFromRequest(req);
BigInteger[] factors = factor(i);
encodeIntoResponse(resp, factors);
}
}
StatelessFactorizer is, like most servlets, stateless: it has no fields and references no fields from other classes. The
transient state for a particular computation exists solely in local variables that are stored on the thread's stack and are
accessible only to the executing thread. One thread accessing a StatelessFactorizer cannot influence the result of
another thread accessing the same StatelessFactorizer; because the two threads do not share state, it is as if they
were accessing different instances.
Is it like every thread has autonomy of execution if no fields is shared?
Each thread has its own program counter, stack, and local variables. There is a term "thread confinement" and one of its forms is called "stack confinement".
Stack confinement is a special case of thread confinement in which an object can only be reached through local variables. Just as encapsulation can make it easier to preserve invariants, local variables can make it easier to confine objects to a thread. Local variables are intrinsically confined to the executing thread; they exist on the executing thread's stack, which is not accessible to other threads.
To read:
Java Concurrency In Practice
Thread Confinement
Stack Confinement using local object reference
Multithreading issues are caused by unwanted changes in state. If there is no state that is changed, there are no such issues. That is also why immutable objects are very convenient in a multithreaded environment.
In this particular case, the method only operates on the input parameters s1 and s2 and no state is kept.
So is it always safe to create a static final Object of whatever class it is pointing to if it has no fields?
"Always" is too strong a claim. It's easy to construct an artificial class where instances are not thread-safe despite having no fields:
public class NotThreadSafe {
private static final class MapHolder {
private static final Map<NotThreadSafe, StringBuilder> map =
// use ConcurrentHashMap so that different instances don't
// interfere with each other:
new ConcurrentHashMap<>();
}
private StringBuilder getMyStringBuilder() {
return MapHolder.map.computeIfAbsent(this, k -> new StringBuilder());
}
public void append(final Object s) {
getMyStringBuilder().append(s);
}
public String get() {
return getMyStringBuilder().toString();
}
}
. . . but that code is not realistic. If your instances don't have any mutable state, then they'll naturally be threadsafe; and in normal Java code, mutable state means instance fields.
XYZComparator is stateless, it has no fields. hence all instances of the class are functionally equivalent. Thus it should be a singleton to save on unnecessary object creation.
From that point of view, the "current day" answer is probably: make MyComparator an enum. The JVM guarantees that MyComparatorEnum.INSTANCE will be a true singelton, and you don't have to worry about the subtle details that you have to consider when building singletons "yourself".
Explanation
So is it always safe to create a static final Object of whatever class it is pointing to if it has no fields?
Depends. Multi-threading issues can only occur when one thread is changing something while another thread is using it at the same time. Since the other thread might then not be aware of the changes due to caching and other effects. Or it results in a pure logic bug where the creator did not think about that a thread can be interrupted during an operation.
So when a class is stateless, which you have here, it is absolutely safe to be used in a multi-threaded environment. Since there is nothing for any thread to change in the first place.
Note that this also means that a class is not allowed to use not-thread-safe stuff from elsewhere. So for example changing a field in some other class while another thread is using it.
Example
Here is a pretty classic example:
public class Value {
private int value;
public int getValue() {
return value;
}
public void increment() {
int current = value; // or just value++
value = current + 1;
}
}
Now, lets assume both threads call value.increment(). One thread gets interrupted after:
int current = value; // is 0
Then the other starts and fully executes increment. So
int current = value; // is 0
value = current + 1; // is 1
So value is now 1. Now the first thread continues, the expected outcome would be 2, but we get:
value = current + 1; // is 1
Since its current was already computed before the second thread ran through, so it is still 0.
We also say that an operation (or method in this case) is not atomic. So it can be interrupted by the scheduler.
This issue can of course only happen because Value has a field value, so it has a changeable state.
YES. It is safe to create a static final object of a class if it has no fields. Here, the Comparator provides functionality only, through its compare(String, String) method.
In case of multithreading, the compare method will have to deal with local variables only (b/c it is from stateless class), and local variables are not shared b/w thread, i.e., each thread will have its own (String, String) copy and hence will not interfere with each other.
Calling the compare method from two threads in parallel is safe (stack confinement). The parameters you pass to the method are stored in that thread's stack, that any other thread cannot access.
An immutable singleton is always recommended. Abstain from creating mutable singletons, as they introduce global state in your application, that is bad.
Edit: If the params passed are mutable object references, then you have to take special care to ensure thread safety.
So I have a non-thread safe API (some vendor software) I'm currently using, and the way we're currently using it is one object per thread. i.e. every thread has:
Foo instance = new Foo();
However, this doesn't appear to work for this particular library. Some non-thread safe bits of it still appear to butt heads, so I'm assuming this library has some static values within it. At a few points where we know that it has issues, we currently are using ReentrantLock to lock the class when need be. I.E.
public class Bar {
protected static final ReentrantLock lock = new ReentrantLock();
public void process() {
Foo instance = new Foo();
boolean locked = false;
try{
if(SomeCondition) {
locked = true;
Bar.lock.lock();
}
*//rest of the processing goes here
} finally {
if(locked){
Bar.lock.unlock();
}
}
}
}
My question is: In such an instance where the class in question is NOT thread safe, even when creating new instances of said class, is it better to use locking, or should I look i be using ThreadLocals instead? Will ThreadLocals even alleviate my actual issue? Does a ThreadLocal version of a class actually force static areas of a class to essentially be non-static?
All a ThreadLocal does is create a lookup where each thread can find its own instance of an object, so that no threads have to share. Conceptually you can think of it as a map keyed by thread id.
Letting each thread use its own objects is a good strategy for some cases, it's called "thread confinement" in the JCIP book. A common example of this is that SimpleDateFormat objects were not designed to be thread-safe and concurrent threads using them generated bad results. Using a ThreadLocal lets each thread use its own DateFormat, see this question for an example.
But if your problem is that the object references static fields, then those static fields exist on the class, not on the instance, so using ThreadLocal doesn't do anything to reduce sharing.
If somehow each of your threads used its own classloader then each would have its own class and the static fields on it would not be shared. Otherwise your locking on the class seems reasonable (though probably not speedy considering all your threads would be contending for the same lock).
The best approach would be working with the vendor to get them to fix their broken code.
ThreadLocal will not solve your problem, ThreadLocal simply store different instance for each thread independently. so in your case if you have shared resource on your 3rd party library level that wouldn't solve the problem.
A simple synchronized monitor will solve the problem, since you want to avoid concurrent access to that library, but be aware of the performance penalty of monitor - only one thread can access the lib concurrently
Just do:
public class Bar {
private static final Object LOCK = new Object();
public void process() {
synchronized(LOCK) {
Foo instance = new Foo();
instance.myMethod();
}
}
Which one among ThreadLocal or a local variable in Runnable will be preferred? For performance reasons. I hope using a local variable will give more chances for cpu caching, etc.
Which one among ThreadLocal or a local variable in Runnable will be preferred.
If you have a variable that is declared inside the thread's class (or the Runnable) then a local variable will work and you don't need the ThreadLocal.
new Thread(new Runnable() {
// no need to make this a thread local because each thread already
// has their own copy of it
private SimpleDateFormat format = new SimpleDateFormat(...);
public void run() {
...
// this is allocated per thread so no thread-local
format.parse(...);
...
}
}).start();
On the other hand, ThreadLocals are used to save state on a per thread basis when you are executing common code. For example, the SimpleDateFormat is (unfortunately) not thread-safe so if you want to use it in code executed by multiple threads you would need to store one in a ThreadLocal so that each thread gets it's own version of the format.
private final ThreadLocal<SimpleDateFormat> localFormat =
new ThreadLocal<SimpleDateFormat>() {
#Override
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat(...);
}
};
...
// if a number of threads run this common code
SimpleDateFormat format = localFormat.get();
// now we are using the per-thread format (but we should be using Joda Time :-)
format.parse(...);
An example of when this is necessary is a web request handler. The threads are allocated up in Jetty land (for example) in some sort of pool that is outside of our control. A web request comes in which matches your path so Jetty calls your handler. You need to have a SimpleDateFormat object but because of its limitations, you have to create one per thread. That's when you need a ThreadLocal. When you are writing reentrant code that may be called by multiple threads and you want to store something per-thread.
Instead, if you want pass in arguments to your Runnable then you should create your own class and then you can access the constructor and pass in arguments.
new Thread(new MyRunnable("some important string")).start();
...
private static class MyRunnable implements {
private final String someImportantString;
public MyRunnable(String someImportantString) {
this.someImportantString = someImportantString;
}
// run by the thread
public void run() {
// use the someImportantString string here
...
}
}
Whenever your program could correctly use either of the two (ThreadLocal or local variable), choose the local variable: it will be more performant.
ThreadLocal is for storing per-thread state past the execution scope of a method. Obviously local variables can't persist past the scope of their declaration. If you needed them to, that's when you might start using a ThreadLocal.
Another option is using synchronized to manage access to a shared member variable. This is a complicated topic and I won't bother to go into it here as it's been explained and documented by more articulate people than me in other places. Obviously this is not a variant of "local" storage -- you'd be sharing access to a single resource in a thread-safe way.
I was also confused why i need ThreadLocal when i can just use local variables, since they both maintain their state inside a thread. But after a lot of searching and experimenting i see why is ThreadLocal needed.
I found two uses so far -
Saving thread specific values inside the same shared object
Alternative to passing variables as parameters through N-layers of code
1:
If you have two threads operating on the same object and both threads modify this object - then both threads keep losing their modifications to each other.
To make this object have two separate states for each thread, we declare this object or part of it ThreadLocal.
Of course, ThreadLocal is only beneficial here because both threads are sharing the same object. If they are using different objects, there's no need for the objects to be ThreadLocal.
2:
The second benefit of ThreadLocal, seems to be a side effect of how its implemented.
A ThreadLocal variable can be .set() by a thread, and then be .get() anywhere else. .get() will retrieve the same value that this thread had set anywhere else. We'll need a globally available wrapper to do a .get() and .set(), to actually write down the code.
When we do a threadLocalVar.set() - its as if its put inside some global "map", where this current thread is the key.
As if -
someGlobalMap.put(Thread.currentThread(),threadLocalVar);
So ten layers down, when we do threadLocalVar.get() - we get the value that this thread had set ten layers up.
threadLocalVar = someGlobalMap.get(Thread.currentThread());
So the function at tenth level does not have to lug around this variable as parameter, and can access it with a .get() without worrying about if it is from the right thread.
Lastly, since a ThreadLocal variable is a copy to each thread, of course, it does not need synchronization. I misunderstood ThreadLocal earlier as an alternative to synchronization, that it is not. It is just a side effect of it, that we dont need to synchronize the activity of this variable now.
Hope this has helped.
This question is answered by the simple rule that a variable should be declared in the smallest possible enclosing scope. A ThreadLocal is the largest possible enclosing scope so you should only use it for data that is needed across many lexical scopes. If it can be a local variable, it should be.