ThreadLocal

概念

ThreadLocal:线程变量,是一个以ThreadLocal对象为键,任意对象为值的一个存储结构。

这个结构被附带在线程上,线程可以根据一个ThreadLocal对象查询到绑定在这个线程的一个值

  • Thread类中有一个成员变量属于ThreadLocalMap,他是一个map类,它的key是ThreadLocal的实例对象
  • 当为ThreadLocal类型的变量执行set操作时,首先获取当前线程的TheadLocalMap变量,然后以ThreadLocal类的对象为key,设定value,get操作类似
  • ThreadLocal变量的活动范围为某线程,是该线程独有的,这里是解决相同变量被多个线程访问的另一种思路ThreadLocal.set()到线程中的对象是该线程自己使用的对象,其他线程是无法访问的,线程终止后,该值作为垃圾被回收
  • ThreadLocal变量的工作原理是:每个线程独自拥有一个变量,对变量的操作是线程本地的操作

set/get注意点

每次set/get值,并不是直接使用线程id作为TheadLocalMap的key,而是使用ThreadLocal作为key

  • 如果直接使用线程id作为key,无法区分放入ThreadLocalMap的多个value
  • 使用ThreadLocal作为key,因为每一个ThreadLocal对象都可以由ThreadLocalHashCode属性唯一区分

那么如何保证ThreadLocalHashCode唯一呢?

​ 在ThreadLocal类中,包含了一个static AtomicInteger nextHashCode类变量和一个static final修饰的常量(作为相邻两个nextHashCode的差值)。因为nextHashCode是类变量,所以每一次创建ThreadLocal对象都可以保证nextHashCode被更新到新的值,并且下一次调用ThreadLocal类这个被更新的值仍然可用,同时使用的AtomicInteger保证每次自增都是原子性的。

ThreadLocal和线程同步机制

他们都是为了解决多线程中相同变量的访问冲突问题

  • 在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量,这时该变量是多个线程共享的,使用同步机制要求程序员分析什么时候对变量进行读写,较为麻烦
  • ThreadLocal从另一个角度出发,它为每一个线程提供了一个独立的变量副本,从而隔离了多个线程对统一变量的访问冲突,因为每一个线程访问/操作的都是自己的本地变量,因此也没有必要对变量进行同步了,ThreadLocal提供了线程安全的共享对象
  • 总的来说,对于多线程资源共享问题,同步机制采取了时间换空间,而ThreadLocal采取了空间换时间,前者提供一份变量,让不同线程排队访问,后者为每一个线程提供一份变量,同时可以相互访问不受影响

ThreadLocalMap

ThreadLocalMap作为hash表的一种实现方式,是通过开放寻址法来解决哈希冲突,与HashMap不同

开放寻址法

  • 如果出现散列冲突,就重新探测一个空闲位置,将其插入,往散列表中插入数据时,如果某个数据经过散列函数散列之后,存储位置已经被占用,我们就从当前位置开始,以此往后寻找,看是否由空闲位置,直到找到为止

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

volatile Previous
redis:单机数据库 Next