AQS(AbstractQueuedSynchronizer)
AQS中核心是一个共享的int类型值叫做state,这个state用来做什么,其实主要看他子类是怎么实现的,比如ReentrantLock这个state是用来做什么的?拿这个state来记录线程到底重入了多少次,比如有一个线程拿到state这个把锁了,state就从0变为1,这个线程又重入一次state就变为2了,再重入就变为3等等,什么时候释放了?从3变为2变为1变为0就释放了,这个就是AQS核心的东西,一个数,这个数代表什么要看子类怎么实现它,那么在这个state核心上还有一堆的线程节点,当然这个节点就是node,每一个node包含一个线程,这么多的线程节点去争用这个state,谁拿到了state就表示谁得到了这把锁,AQS的核心就是一个共享的数据一堆互相竞争的线程,这就是AQS。
ThreadLocal
ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
threadLocal.set(new Object());
//ThreadLocal#set
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
//ThreadLocal#getMap
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
代码比较简单,先获取当前的线程,再根据当前线程对象获取到该对象的成员变量threadLocals,再赋值到对象里的threadLocals。
这个时候就明白了为什么ThreadLocal是线程本地变量。
为什么要使用ThreadLocal?
声明型事务,每个线程都有自己的Connection。
java的四种引用:强软弱虚
- 强引用:只要有一个引用指向这个对象,那么垃圾回收一定不会回收它。
- 软引用:当有一个对象(字节数组)被一个软引用所指向的时候,只有内存不够用的时候才会回收它。(使用场景:做缓存用)
- 弱引用:只要遭遇到GC就会回收。
最经典的一个应用ThreaLocal
...
ThreadLocal<Object> tl = new ThreadLocal<Object>();
tl.set(new Object());
...
//ThreadLocal#set
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
...
//ThreadLocal 内部类
static class Entry extends WeakReference<ThreadLocal<?>> {
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
/**
* 为什么使用Entry?
如果是强引用,tl 如果在代码中设置为null,但是线程中的key还是指向ThreadLocal对象,垃圾回收不会回收,会造成内存泄漏。
改为弱引用之后,ThreadLocal被回收,key变为null值,但val再也无法被访问到,因此依然可能造成内存泄漏,所以避免这种情况的话每次使用完还需要remove掉。
tl.remove()
*/
- 虚引用:引用队列感知垃圾回收,大多用于管理堆外内存。
public PhantomReference(T referent, ReferenceQueue<? super T> q)