当前位置:网站首页>Detailed explanation of ThreadLocal
Detailed explanation of ThreadLocal
2022-06-27 01:47:00 【ZNineSun】
1.ThreadLocal brief introduction
stay java In the thread , Each thread has one ThreadLocalMap Instance variables ( If not used ThreadLocal, Will not create this Map, The first time a thread accesses a ThreadLocal variable , Will create ).
ThreadLocal It's easy to be literal , Take it for granted that it's a “ Local thread ”. Actually ,ThreadLocal Not one Thread, It is Thread Local variables of , Maybe name it ThreadLocalVariable It's easier to understand .
It mainly consists of four methods initialValue(),get(),set(T),remove(), Among them, it is worth noting that initialValue(), The method is a protected Methods , Obviously it's specifically implemented for subclass rewriting . This method returns the initial value of the current thread's local variable in this thread , This method is a delay call method , In a thread 1 Secondary call get() Execution only , And only execute 1 Time ( namely : Call this method at most once each time you access a thread to get a local variable for each thread , The first time a thread uses get() Method to access variables . If the thread precedes get Method call set(T) Method , Will not be called again in the thread initialValue Method ).ThreadLocal The default implementation in returns a null:
The Map It is solved by linear detection hash The question of conflict , If you don't find free slot, Just keep trying back , Until you find a free place , Insert entry, This way is often encountered in hash When the conflict , Affect efficiency .
Let's discuss it in detail ThreadLocal.
2.ThreadLocal The role of
ThreadLocal The main function of this system is to isolate data ,ThreadLocal The variables filled in belong to the current thread , This variable is isolated from other threads , That is, this variable is unique to the current thread .
ThreadLocal A copy of the variable is created in each thread , Then each thread can access its own internal copy variables .
When it comes to isolation , It should not be difficult for us to get in touch with Isolation of transactions , you 're right ,Spring To realize transaction isolation, we use Threadlocal The way , To ensure that database operations in a single thread use the same database connection , meanwhile , In this way, the business layer does not need to sense and manage the transaction when using it connection object , Through the propagation level (@Transaction), Skillfully manage switching between multiple transaction configurations , Suspend and resume .
Spring It's used in the frame ThreadLocal To achieve this isolation , Mainly in the TransactionSynchronizationManager In this class :
It's worth noting that :Spring The main business is ThreadLocal and AOP To do what is realized
besides , We are using SimpleDataFormat It also uses , Maybe you're using SimpleDataFormat It's just simple new One. SimpleDataFormat object , But when we use SimpleDataFormat Of parse() When the method is used , The method has a Calendar object , call SimpleDataFormat Of parse() Method will call first Calendar.clear(), And then call Calendar.add(), If a thread calls first add() Then another thread calls clear(), Now parse() The time to parse the method is wrong .
The easiest way to solve this problem is to make every thread new One's own SimpleDataFormat Just fine , But the big problem is if we have 1000 It's a thread new1000 individual SimpleDataFormat?
So we can use the thread pool to add ThreadLocal packing SimpleDataFormat, Call again initialValue Let each thread have a SimpleDataFormat Copy of , This solves the problem of thread safety , It also improves performance .
You think there are only so many places to use threadLocal??? take it easy , If a thread exists in a project, it often encounters calls across several methods , The object that needs to be passed , That is context (Context), It's a state , Often it's user identity 、 Mission information, etc , There will be the problem of transitional transmission .
If we use a similar responsibility chain model , Add one to each method context The parameters are very cumbersome , And sometimes , If the call chain has a third-party library that cannot modify the source code , Object parameters will not be passed in , So we use ThreadLocal I made a little transformation , This only needs to be done before the call ThreadLocal Setting parameters in , other place get Just a moment , Just like below :
meanwhile , Like we often use cookie,session Data isolation is done through ThreadLocal To do what is realized .
I also mentioned above ThreadLocal It is mainly used for data isolation , So it's with Synchronized What's the difference ?
3.ThreadLocal And Synchronized The difference between
ThreadLocal In fact, it is a variable bound to the thread .ThreadLocal and Synchonized Are used to solve multithreaded concurrent access .
however ThreadLocal And synchronized There are essential differences :
1、Synchronized For data sharing between threads , and ThreadLocal It is used for data isolation between threads .
2、Synchronized It's using the lock mechanism , Make variables or code blocks accessible to only one thread at a time .
and ThreadLocal A copy of the variable is provided for each thread , So that each thread at a certain time access is not the same object , This isolates multiple threads from sharing data .
and Synchronized But the opposite is true , It is used to obtain data sharing when communicating among multiple threads .
Simply speaking ThreadLocal,threadlocl Is a property in the current thread ThreadLocalMap One of the sets Entry Of key value Entry(threadlocl,value), Although different threads threadlocal This key The value is the same , But what different threads have ThreadLocalMap It's unique , That is, different threads share the same ThreadLocal(key) Corresponding to the stored value (value) Dissimilarity , Thus, the purpose of variable isolation between threads is achieved , But in the same thread, this value The variable address is the same .
4.ThreadLocal The underlying implementation of
ThreadLocal<String> localName = new ThreadLocal();
localName.set(" Zhang San ");
String name = localName.get();
localName.remove();
The code above is very simple : stay ThreadLocal Store an element , Then go to get it, and finally remove this element , As a whole ThreadLocal Just these three basic operations :
set、get、remove
Let's take a look at the source code in turn :
4.1 set
set It's very simple : Mainly ThreadLocalMap We need to focus on , and ThreadLocalMap The current thread Thread One is called threadLocals From the variable of .
See here , We have actually discovered ThreadLocal The truth about data isolation .
Every thread Thread They all maintain their own threadLocals Variable , So create in each thread ThreadLocal When , In fact, data exists in its own thread Thread Of threadLocals In variables , No one else can get it , So isolation is achieved .
I mentioned one above ThreadLocalMap,ThreadLocalMap What does the underlying structure look like ?
4.2 ThreadLocalMap
Let's take a look at the source code shown in the figure above ,
Since there is a Map So his data structure is very similar to HashMap Of , But look at the source code can find , It didn't come true Map Interface , And his Entry It's inheritance WeakReference( Weak reference ) Of , I didn't see HashMap Medium next, So there's no linked list .
Let me briefly explain weak references : Weak references are mainly used in cases where they are not blocked key perhaps value Recycled mapping, What does that mean ? Weak references are created for garbage collection services . It refers to an object , But it does not prevent the object from being recycled . If you use a strong reference , As long as the reference exists , Then the referenced object cannot be recycled . Weak references don't have this problem . While the garbage collector is running , If all references to an object are weak references , The object will be recycled .
There's a problem , How to solve the problem without the linked list Hash What about the conflict ?
threadlocalmap Structure is entry Array , We can have more than one thread in the development process TreadLocal To store different types of objects , But they will all be put into your current thread ThreadLocalMap in , So you have to store arrays .
As for the specific solution hash Conflicting , Let's talk about the source code first :
See from the source code ThreadLocalMap When it's stored, it's going to give each one ThreadLocal Object to one threadLocalHashCode, During insertion , according to ThreadLocal Object's hash value , Locate the table Position in i,int i = key.threadLocalHashCode & (len-1).
Obviously this is a very simple linear detection method , So solve it hash The way of conflict is Linear detection method
And then we will judge : If the current position is empty , Just initialize one Entry Put the object in position i On .
If the position i Not empty , If this Entry Object's key It's just about to be set up key, So refresh Entry Medium value;
If the position i Is not empty , and key It's not equal to entry, Then find the next empty position , Until it's empty .
The overall process is shown in the figure below :
thus , stay get When , According to ThreadLocal Object's hash value , Locate the table Position in , Then judge the position Entry Object key Whether and get Of key Agreement , If it's not consistent , Just judge the next position ,set and get If the conflict is serious , The efficiency is still very low .
4.3 get
This is the picture above get All processes of
Speaking of this, many people may be thinking ThreadLocal Where are instances of and their values stored ?
stay Java in , Stack memory belongs to a single thread , Each thread will have a stack memory , The stored variables can only be seen in the thread to which they belong , That is, stack memory can be understood as thread's private memory , Objects in the heap memory are visible to all threads , Objects in heap memory can be accessed by all threads .
But it can't be said that ThreadLocal The instance of and its value are stored on the stack , although threadLocal The median value is private to each thread ,ThreadLocal An instance is actually held by the class it creates ( The top should be held by the thread ), and ThreadLocal The value of is actually held by the thread instance , They're all on the pile , We just changed the visibility to thread visibility through some tricks .
5. Shared thread ThreadLocal data
Use InheritableThreadLocal It can be accessed by multiple threads ThreadLocal Value , We create a... In the main thread InheritableThreadLocal Example , And then get this in the child thread InheritableThreadLocal Instance settings .
public void test() {
final ThreadLocal threadLocal = new InheritableThreadLocal();
threadLocal.set("ninesun");
Thread t = new Thread() {
@Override
public void run() {
super.run();
System.out.println(" Get stored values :" + threadLocal.get());
}
};
t.start();
}
Okay , We now know how to use InheritableThreadLocal It can be accessed by multiple threads ThreadLocal Value , But how are these values passed between child threads ?
The logic of transmission is simple ,
The picture above is what I intercepted Thead Inside the code snippet ,thread When initializing the creation ( In the constructor ) There are the following operations :
This code is also very simple , Roughly speaking : If the thread's inheritThreadLocals Variable is not empty , And the parent thread's inheritThreadLocals Also exist , So I'll take the parent thread's inheritThreadLocals For the current thread inheritThreadLocals. Let's take our example above .
ThreadLocal I've been talking about it for the most part , But you may not realize the seriousness of the problem , Because it said ,key Is a weak reference , and value But strong citation , If we're using threadLocal Improper operation , It will lead to a very serious consequence : Memory leak
6. Memory leak
We can see ,ThreadLocal When you save it, you think of yourself as Key There is ThreadLocalMap in , The normal situation should be key and value Should be strongly quoted by the outside world , But now key Designed to WeakReference A weak reference to .
This is the picture above key By GC Later scenes .
The reason for the above scenario comes from The life cycle of a weakly referenced object
Objects with only weak references have a shorter life cycle , In the process of the garbage collector thread scanning the memory area it governs , Once you find an object with only weak references , Whether the current memory space is enough or not , Will reclaim its memory .
however , Because the garbage collector is a low priority thread , So it's not necessarily easy to find objects with only weak references .
This leads to a problem ,ThreadLocal When there is no external strong reference , happen GC Will be recycled , If you create ThreadLocal The thread of has been running , So this Entry Object value It's possible that they won't be recycled , Memory leak .
This may not be very intuitive , Let me give you a simple example :
For example, the threads in the thread pool , Threads are reusable , After the previous thread instance has been processed , Threads are still alive for reuse purposes , therefore ,ThreadLocal Set value Value is held , Causing a memory leak .
How can we solve it ?
The solution is too simple , At the end of the code remove Just fine , We just need to remember to use at the end of use remove Just clear the value .
such as , Our previous code is :
public void test() {
final ThreadLocal threadLocal = new InheritableThreadLocal();
threadLocal.set("ninesun");
}
Then we can go through :
public void test() {
final ThreadLocal threadLocal = new InheritableThreadLocal();
try {
threadLocal.set("ninesun");
} finally {
threadLocal.remove();
}
}
remove The source code is also very simple , As shown in the figure above , Is to find the corresponding values and set them to blank , So when the garbage collector is recycling , They're automatically recycled .
So here comes the question , Why do we have to key Designed as weak reference ?
7.ThreadLocalMap Of key Design it as a weak reference ?
key If it is not set to weak reference, it will cause and entry in value The same memory leak scenario .
If threadlocalmap Of key Is a strong quote , So as long as the thread exists , threadlocalmap There is a , and threadlocalmap Structure is entry Array . That is, the corresponding entry Arrays exist , and entry Of array elements key yes threadLocal.
Even if we explicitly assign values in the code threadlocal by null, tell gc To garbage collect this object . Due to the strong reference above , threadlocal Even if the assignment is null, As long as the thread exists , threadlocal It's not recycled .
And set to weak reference , gc When the scan arrives , Find out threadlocal No strong references , Will recycle the threadlocal object .
also threadlocal Of set get remove Will judge whether key by null, If null, that value Will also be removed , After that will be gc Recycling .
ThreadLocal Deficiency , Such as using the least efficient linear detection method to solve conflicts , You can see netty Of fastThreadLocal To make up for .《 Talk about FastLocal Why so fast 》
边栏推荐
猜你喜欢
Simply learn the entry-level concepts of googlecolab
执念斩长河暑期规划
1.44寸TFT-LCD显示屏取模教程
博日科技招股书失效,中金公司已停止对其辅导,放弃港交所上市?
做了两天的唯美蝴蝶动画
I encountered some problems when connecting to the database. How can I solve them?
Ml: a detailed introduction to the division of the top ten roles, backgrounds, responsibilities and outputs of the machine learning engineering team
SystemVerilog仿真速率提升
lottie.js创意开关按钮动物头像
1.44 inch TFT-LCD display screen mold taking tutorial
随机推荐
svg拖拽装扮Kitty猫
Two days of beautiful butterfly animation
Clip: learning transferable visual models from natural language monitoring
Weibo comments on high performance and high availability architecture
UVM in UVM_ config_ Use of DB in sequence
Memcached foundation 9
get_sequencer的用法总结
使用命令行安装达梦数据库
简单学习GoogleColab的入门级概念
Oracle/PLSQL: Translate Function
markdown表格(合并)
CLIP:从自然语言监督中学习可迁移的视觉模型
memcached基础15
Oracle/PLSQL: Replace Function
SystemVerilog仿真速率提升
Learn the most basic operation of discodiffusion
UVM in UVM_ report_ Enabled usage
Oracle/PLSQL: CharToRowid Function
Parameter transfer method between two pages
“所有专业都在劝退”,对大学生最友好的竟然是它?