In-depth understanding of threadlocal (June 11, 2015)

Source: Internet
Author: User

Note: Turn from: http://my.oschina.net/clopopo/blog/149368

Learn a thing first to know why to introduce it, is what we can use it to do. So let's take a look at what threadlocal does for us, and then see how it works.

Threadlocal If you simply look at the name as a "local thread" that means that the name is really not very good, it is easy to misunderstand, threadlocalvariable (thread local variable) should be a better name. Let's take a look at the official description of Threadlocal:

This class provides thread-local (thread-local) variables. These variables are different from their ordinary counterparts, because each thread that accesses a variable (through its Get or set method) has its own local variable, independent of the initialized copy of the variable. ThreadLocal instances are typically private static fields in a class that want to associate the state with a thread (for example, a user ID or transaction ID).
We pick out the key points:

1. Each thread has its own local variable

Each thread has a context that is separate from the other threads to hold the variable, and the local variables of one thread are not visible to other threads (with the premise, explained later)

2, independent of the initialization of the variable copy

Threadlocal can give an initial value, and each thread will get a copy of the initialization value to ensure that different threads have a copy.

3, the State and a certain line Threads association

ThreadLocal is not used to solve the problem of shared variables, not to reconcile thread synchronization, but to facilitate the introduction of a mechanism for each thread to handle its own state, understanding this is critical to the correct use of ThreadLocal.

Let's look at a simple example:

publicclass ThreadLocalTest {

//创建一个Integer型的线程本地变量

publicstatic final ThreadLocal<Integer> local = new ThreadLocal<Integer>() {

@Override

protectedInteger initialValue() {

return0;

}

};

publicstatic void main(String[] args) throws InterruptedException {

Thread[] threads = newThread[5];

for(int j = 0; j < 5; j++) {      

threads[j] = newThread(new Runnable() {

@Override

publicvoid run() {

//获取当前线程的本地变量,然后累加5次

intnum = local.get();

for(int i = 0; i < 5; i++) {

num++;

}

//重新设置累加后的本地变量

local.set(num);

System.out.println(Thread.currentThread().getName() + " : "+ local.get());

}

}, "Thread-"+ j);

}

for(Thread thread : threads) {

thread.start();

}

}

}

Post-run results:

Thread-0:5
Thread-4:5
Thread-2:5
Thread-1:5
Thread-3:5

As we can see, each thread's cumulative result is 5, each thread processes its own local variable value, and the threads do not affect each other.

Let's look at one more example:

publicclass ThreadLocalTest {

privatestatic Index num = new Index();

//创建一个Index类型的本地变量

privatestatic ThreadLocal<Index> local = new ThreadLocal<Index>() {

@Override

protectedIndex initialValue() {

returnnum;

}

};

publicstatic void main(String[] args) throws InterruptedException {

Thread[] threads = newThread[5];

for(int j = 0; j < 5; j++) {

threads[j] = newThread(new Runnable() {

@Override

publicvoid run() {

//取出当前线程的本地变量,并累加1000次

Index index = local.get();

for(int i = 0; i < 1000; i++) {                                        

index.increase();

}

System.out.println(Thread.currentThread().getName() + " : "+ index.num);

}

}, "Thread-"+ j);

}

for(Thread thread : threads) {

thread.start();

}

}

staticclass Index {

intnum;

publicvoid increase() {

num++;

}

}

}

After execution we found the following results (each run is not the same):

Thread-0:1390
Thread-2:2390
Thread-4:4390
Thread-3:3491
Thread-1:1390

Why does the thread local variable fail again this time? You can look carefully at the above code to find out the reason first.

-----------------------------------------------low-key split-line-------------------------------------------

Let's take another look. "Threadlocal can give an initial value, and each thread will get a copy of this initialization value." "Copy of initial value ... "It seems to think of something." Let's take a look at the places in the code above that define threadlocal.

privatestatic Index num = new Index();

privatestatic ThreadLocal<Index> local = new ThreadLocal<Index>() {

@Override

protectedIndex initialValue() {

returnnum;       // 注意这里,返回的是已经定义好的对象num,而不是new Index()

}

};

In the above code, we provide an initial value for our threadlocal by overriding the InitialValue function, and each thread gets a copy of the initial value. And now our initial value is a well-defined object, and num is a reference to that object. In other words our initial value is a reference. Is the referenced copy and reference pointing to the same object?

What if we want to save an index object for each thread? That is to create a copy of the object instead of the object reference:

privatestatic ThreadLocal<Index> local = new ThreadLocal<Index>() {

@Override

protectedIndex initialValue() {

returnnew Index(); //注意这里

}

};

Copy diagram of the object:

Now we should be able to understand the meaning of threadlocal local variables. Next we will look at the source of threadlocal, from the inside to reveal its mystery.

Threadlocal has an internal class threadlocalmap, the implementation of this class accounted for the entire Threadlocal class source code more than half. The role of this threadlocalmap is critical, and it is a container for threads to actually save the thread's own local variables. Each thread has its own separate instance of Threadlocalmap, and all its local variables are saved to this map. Now let's start with the two most common methods of threadlocal get and set:

publicT get() {

//获取当前执行线程

Thread t = Thread.currentThread();

//取得当前线程的ThreadLocalMap实例

ThreadLocalMap map = getMap(t);

//如果map不为空,说明该线程已经有了一个ThreadLocalMap实例

if(map != null) {

//map中保存线程的所有的线程本地变量,我们要去查找当前线程本地变量

ThreadLocalMap.Entry e = map.getEntry(this);

//如果当前线程本地变量存在这个map中,则返回其对应的值

if(e != null)

return(T)e.value;

}

//如果map不存在或者map中不存在当前线程本地变量,返回初始值

returnsetInitialValue();

}

It is emphasized that the thread object has an attribute threadlocals of type Threadlocalmap, which is dedicated to saving all of its thread-local variables. This property is null when the thread object is initialized. Therefore, the Threadlocals property needs to be initialized for the first time that a thread object is used on a thread-local variable. Note that the "thread first uses local thread variable" and "use a thread-local thread variable for the first time" are distinguished.

Getmap Method:

//直接返回线程对象的threadLocals属性

ThreadLocalMap getMap(Thread t) {

returnt.threadLocals;

}

Setinitialvalue method: (Look at the previous example after reading it)

privateT setInitialValue() {

//获取初始化值,initialValue 就是我们之前覆盖的方法

T value = initialValue();

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

//如果map不为空,将初始化值放入到当前线程的ThreadLocalMap对象中

if(map != null)

map.set(this, value);

else

//当前线程第一次使用本地线程变量,需要对map进行初始化工作

createMap(t, value);

//返回初始化值

returnvalue;

}

Let's take a look at the Set method

publicvoid set(T value) {

Thread t = Thread.currentThread();

ThreadLocalMap map = getMap(t);

if(map != null)

map.set(this, value);

//说明线程第一次使用线程本地变量(注意这里的第一次含义)

else

createMap(t, value);

}

Thradlocal also has a remove method, let's analyze:

publicvoid remove() {

//获取当前线程的ThreadLocalMap对象

ThreadLocalMap m = getMap(Thread.currentThread());

//如果map不为空,则删除该本地变量的值

if(m != null)

m.remove(this);

}

Here everyone should be more clear about the threadlocal variable, as to the implementation of THRADLOCALMAP details here is not said. We are interested to see the source of threadlocal.

In-depth understanding of threadlocal (EXT) (June 11, 2015)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.