Skip to content

Latest commit

 

History

History
89 lines (67 loc) · 2.36 KB

File metadata and controls

89 lines (67 loc) · 2.36 KB

ThreadLocal底层原理分析

什么是线程安全?

原子性、可见性、有序性

怎么解决安全性问题?

1、锁

2、ThreadLocal提供了一个线程范围的局部变量,线程级别的隔离

public class ThreadLocalApp {
    //private static int num = 0;
    static ThreadLocal<Integer> num = new ThreadLocal<Integer>() {
        protected Integer initialValue() {
            return 0;
        };
    };

    // 1.每个贤臣的变量副本是如何存储的?
    // 2.ThreadLocal是什么时候初始化的

    public static void main(String[] args) {
        Thread[] threads = new Thread[5];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(() -> {
                int localNum = num.get(); // 获得ThreadLocal钟本地初始化的值
                localNum += 5;
                num.set(localNum); // 设置修改以后的值
                System.out.println(Thread.currentThread().getName() + ":" + num.get());
            }, "thread-" + i);
        }

        for (Thread t : threads) {
            t.start();
        }
    }
}

ThreadLocal副本图解

image-20220305140847609

一个线程中多个ThreadLocal如何存储

private void set(ThreadLocal<?> key, Object value) {

    // We don't use a fast path as with get() because it is at
    // least as common to use set() to create new entries as
    // it is to replace existing ones, in which case, a fast
    // path would fail more often than not.

    Entry[] tab = table;
    int len = tab.length;
    int i = key.threadLocalHashCode & (len-1); // 斐波那契分布

    for (Entry e = tab[i];
         e != null;
         e = tab[i = nextIndex(i, len)]) {
        ThreadLocal<?> k = e.get();

        if (k == key) {
            e.value = value;
            return;
        }
        // 什么时候key为null?
        // 弱引用key为null,则直接替换
        if (k == null) {
            replaceStaleEntry(key, value, i);
            return;
        }
    }

    tab[i] = new Entry(key, value);
    int sz = ++size;
    if (!cleanSomeSlots(i, sz) && sz >= threshold)
        rehash();
}

image-20220305142621905

如果超过16个就扩容