多线程和高并发系列(二)

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 threadLocal = new ThreadLocal();
        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 tl = new ThreadLocal();
        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> {
            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 q)

你可能感兴趣的:(多线程和高并发系列(二))