Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Including the ThreadContext when writing log4j2 logs via a Java Static method - Is it thread safe?

In a web service application I am using a static method to set log4j ThreadContext variables for logging purposes as below,

public static void setLogParams(String company_id, String userId) {
    ThreadContext.put("company_id_val", company_id);
    ThreadContext.put("user_id_val", userId);
}

Each and every web service requests will be call above method initially and then loj4j Logger object will use for do the rest. Above given values are not same every time and may vary request to request.

My question: Is above scenario is thread safe? Will different web service requests share the same company_id and user_id since both of these parameters are holding same references? Then it will be confusing. Should I use a non-static method instead?

I did gone through the similar question below

Are non-synchronised static methods thread safe if they don't modify static class variables?

But I need to clarify this.

like image 860
Supun Avatar asked Jul 03 '15 08:07

Supun


People also ask

Is ThreadContext thread-safe?

​ The SAP Cloud SDK for Java provides a so-called ThreadContext . It serves as thread-safe storage for potentially sensitive information.

Is log4j2 thread-safe?

Yes, log4j is thread-safe. Log4j components are designed to be used in heavily multithreaded systems.

What is ThreadContext in log4j2?

The ThreadContext allows applications to store information either in a Map or a Stack. The MDC is managed on a per thread basis. To enable automatic inheritance of copies of the MDC to newly created threads, enable the "isThreadContextMapInheritable" Log4j system property.

Are static methods thread-safe Java?

A data type or static method is threadsafe if it behaves correctly when used from multiple threads, regardless of how those threads are executed, and without demanding additional coordination from the calling code.


1 Answers

In short

It's safe.

Explanation

ThreadContext is a map that is scoped to every thread. Casually spoken, every thread has its own instance of a map, and the values are not visible to the other threads. See https://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html for more details on the topic of thread locals. It does not matter, whether the method, in which you set the ThreadContext is static or not.

There is one caveat: Java application servers/web servers use thread pooling and reuse threads. This means once a thread finished it's web request, it is reused to process the next request. The data within the ThreadContext remains and is valid for the next request. Retaining data for the next request is usually not desirable. You should clear the ThreadContext after you're done with the request:

try{
    setLogParams(company_id, userId);
    ... // do your business logic
} finally {
    clearLogParams(); // Something like ThreadContext.clear();
}

Update: I did not cover the static/unsynchronized method part but here's the answer to this:

Your method does not store the parameters in your own storage; rather it stores them within the ThreadContext. Arguments (no matter whether they are in a static or non-static method) do not overlap between calls and threads. The lifecycle of an argument ends with the end of the method call (as long as you do not store the data, but references are a different topic).

You would run into race conditions if you stored the customer_id for example by your own in a static variable:

class RequestDataHolder {
   // this is not thread safe since multiple threads access the same data
   public static String customer_id;

   public static void setLogParams(String company_id, String userId){
      RequestDataHolder.customer_id = customer_id;
   }
}

You would have to synchronize all method calls to guarantee one-after-one operations that would turn your whole system effectively into a system that behaves like single-threaded but with multiple threads and massive drawbacks.

Static methods are not related to static variables when it comes to synchronization. There are however scenarios, where you can invoke synchronized non-static methods that behave differently, but that leads us too far from your original question.

like image 182
mp911de Avatar answered Oct 05 '22 00:10

mp911de