problem
Web project, each time a user login system will redis Session information is stored, and then returned to the client token, the token user session as indicated, all subsequent requests will take an interceptor, this interceptor based on the Session token information take redis from the back into a ThreadLocal. When more concurrent, Session information about the error happens.
The analysis error process is: 1 user log in and access the system at this time using Session information and user thread A 1 to thread A deposit of TheadLocal, then a user is not logged 2 also access the system, server allocates the threads again a to handle the request, then the user to take 2 to 1 Session information of the user.
ThreadLocal
TheadLocal is shared thread variable jdk provides a very easy to use tool. When developing Web, the server may be used to store request TheadLocal Request, Response. In the method shown in the call stack without passing. Any place can easily call stack in the thread method to get our deposit into the instance variables.
class WebContext {
private TheadLocal<HttpServletRequest> request = new TheadLocal<>();
private TheadLocal<HttpServletResponse> response = new TheadLocal<>();
public static void setRequest(HttpServletRequest req) {
request.set(req);
}
public static HttpServletRequest getRequest() {
request.get();
}
public static void setResponse(HttpServletResponse resp) {
response.set(resp);
}
public static HttpServletResponse getResponse() {
response.get();
}
}
class AbcController {
public Object userInfo() {
HttpServletRequest request = WebContext.getRequest();
// request.getParameter()
// ...
}
}
复制代码
Look TheadLocal code:
// TheadLocal两个重要的方法
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
复制代码
TheadLocal either set or get method method will first Thread t = Thread.currentThread();
obtain the current thread instance. Then get TheadLocalMap instance thread instance ThreadLocalMap map = getMap(t);
which is why acquiring thread variable will win the same instance in the same thread, because each thread instance variables are stored in its own thread so that these variables are thread-safe.
public class Thread implements Runnable {
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
}
复制代码
These are the Thread class declaration of threadLocals
property. It can be seen that the thread variable actual storage ThreadLocal.ThreadLocalMap
class, storage key and the like on Map (Key-Value), which is threaded Key example, Value is a variable thread.
Tomcat thread pool
Because the operating system to create a thread that is resource-consuming, so many applications will use thread pool mode, system initialization is to create a certain amount of one-time, multiplex these threads will share, that is not used up after thread It will be destroyed until the application is stopped.
Result of this is that different user requests reuse the same thread leads to the same Session information obtained by different users, causing confusion Session information.
solve
In one arrangement an interceptor, the requested 前端
setting information to the local Session thread variable, the 后端
Session information emptying thread-local variables.
// 代码简化了
public class SessionInspector extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(...) throws Exception {
// ThreadLocal.set(Session)
return true;
}
public void afterCompletion(...) {
// ThreadLocal.clear()
}
}
复制代码
to sum up
ThreadLocal provides a convenient way to share variable in the thread for us to provide a guarantee of data thread-safe manner. But consider the case of a thread in a multithreaded environment, reuse, if ThreadLocal
within the save information is information related to the user's session, etc. At the end of the thread to clean up the task ThreadLocal
information in the.