什么是线程安全?
原子性、可见性、有序性
怎么解决安全性问题?
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();
}
}
}
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();
}
如果超过16个就扩容