threadlocal

并发编程(四)—— ThreadLocal源码分析及内存泄露预防

眉间皱痕 提交于 2020-02-07 09:49:50
今天我们一起探讨下ThreadLocal的实现原理和源码分析。首先,本文先谈一下对ThreadLocal的理解,然后根据ThreadLocal类的源码分析了其实现原理和使用需要注意的地方,最后给出了两个应用场景。相信本文一定能让大家完全了解ThreadLocal。 ThreadLocal是什么?   ThreadLocal是啥?以前面试别人时就喜欢问这个,有些伙伴喜欢把它和线程同步机制混为一谈,事实上ThreadLocal与线程同步无关。ThreadLocal虽然提供了一种解决多线程环境下成员变量的问题,但是它并不是解决多线程共享变量的问题。那么ThreadLocal到底是什么呢?   ThreadLocal很容易让人望文生义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的 局部变量 ,也许把它命名为ThreadLocalVariable更容易让人理解一些。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是Java中一种较为特殊的线程绑定机制,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。   通过ThreadLocal存取的数据,总是与当前线程相关,也就是说,JVM 为每个运行的线程,绑定了私有的本地实例存取空间

浅谈java中的ThreadLocal类

你离开我真会死。 提交于 2020-02-06 22:10:40
在谈ThreadLocal之前,先简单说一下一致性问题及其解决方法。 1.一致性问题 发生在多个主体对同一份数据无法达成共识。包括分布式一致性问题、并发问题等。特点是场景多、问题复杂、难以察觉——需要严密的思考甚至数学论证。 2.一致性问题解决方法 一致性问题的解决方法通常有3个。第一 排队 :比如,锁、互斥量、管程、屏障等。第二 投票 :例如,paxos、Raft等。这两种都会产生额外的开销。还有一种是 避免 产生一致性问题:比如 ThreadLocal 等,为解决多线的并发问题提供了新的思路。 3.ThreadLocal是什么 定义:提供 线程局部 变量;一个线程局部变量在多个线程中,分别有独立的值(副本)。 特点:简单(开箱即用)、快速(无额外开销)、安全(线程安全) 场景:多线程环境下,资源持有、线程一致性、并发计算、线程安全等场景。 4.ThreaLocal的API 构造函数ThreadLocal<T>() 初始化 initialValue() 访问器 get/set 回收 remove ThreadLocal能使线程中的某个值与保存值的对象关联起来。它提供了get和set等访问方法,这些方法为每个使用该变量的线程都存有一份独立的副本,因此get总是返回由当前执行线程在调用set时设置的最新值。 5.ThreadLocal的简单实用

ThreadLocal的使用及原理

我是研究僧i 提交于 2020-02-06 17:59:10
一、概述 ThreadLocal简单理解就是针对一个线程做资源的共享,通过set()方法把某些资源放到线程中保存,然后通过get方法获取这个资源。它的出现解决了同一个线程中,不同类的方法中可以共享同一个对象或者变量问题。注意他不是为解决并发中多线程的资源共享,这种场景一般需要加锁。而是为了在多线程之间维护每个线程单独持有的资源,不需要加锁。 可以想象ThreadLocal的使用场景是在一个线程中共享数据库连接,虽然我没有看过mybatis,hibernate的源码(后面会研究),但估计这些框架中少不了ThreadLocal。另外在java读写锁中使用ThreadLocal用来保存一个线程重入读锁的次数。 下面我们从ThreadLocal的基础代码结构开始了解源码实现。 二、基础代码结构 以下代码先不用细究,等看了后面set()方法再来认真阅读也可以。从下面代码中我们要明白两个事情: ThreadLocal和对应的变量都是保存在内部类ThreadLocalMap的table数组中。 ThreadLocalMap的Entry使用了弱引用,我们后面会讲解这里使用弱引用的好处。 public class ThreadLocal < T > { /** 生成ThreadLocal的哈希码 */ private final int threadLocalHashCode =

ThreadLocal的弱引用

我是研究僧i 提交于 2020-02-05 04:51:58
ThreadLocal中,获取到线程私有对象是通过线程持有的一个threadLocalMap,然后传入ThreadLocal当做key获取到对象的,这时候就有个问题,如果你在使用完ThreadLocal之后,将其置为null,这时候这个对象并不能被回收,因为他还有 ThreadLocalMap->entry->key的引用,直到该线程被销毁,但是这个线程很可能会被放到线程池中不会被销毁,这就产生了内存泄露,jdk是通过弱引用来解决的这个问题的,entry中对key的引用是弱引用,当你取消了ThreadLocal的强引用之后,他就只剩下一个弱引用了,所以也会被回收。 看代码 threadLocal是一个强引用,引用了堆中ThreadLocal对象A,然后调用set方法时,在当前线程的threadLocalMap中也引用了对象A,即entry中的key,如果entry中的key不设为弱引用的话,就会存在上面说的对象A内存泄露的问题。 ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(); threadLocal.set(1); threadLocal.get(); threadLocal = null; 作者:吕清海 链接:https://www.zhihu.com/question/37401125/answer

ThreadLocal理解

北城以北 提交于 2020-02-04 22:53:08
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。 各个线程中访问的是不同的对象。 另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。 通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。 如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 下面来看一个hibernate中典型的ThreadLocal的应用: private static final ThreadLocal threadSession = new ThreadLocal(); public static Session

Spring整合mybatis, @MapperScan 原理(spring-mybatis)

≯℡__Kan透↙ 提交于 2020-02-04 21:01:02
@MapperScan("com.lz.springboot.mybatis.springbootmybatis.mapper") 定义mapper接口扫面位置 @Import(MapperScannerRegistrar.class) mapper扫描注册器 扫描目标包下的mapper接口 MapperScannerRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware 覆盖 registerBeanDefinitions 方法使用JDK动态代理创建代理对象,并加入spring ioc容器中 ClassPathMapperScanner 注册 basePackage 中的 mapper MapperFactoryBean 工厂bean方式返回具体的代理对象 @Override public T getObject() throws Exception { return getSqlSession().getMapper(this.mapperInterface); } MapperProxyFactory 利用JDK动态代理创建对象 protected T newInstance(MapperProxy<T> mapperProxy) { return (T) Proxy

JAVA多线程之ThreadLocal类

与世无争的帅哥 提交于 2020-02-04 20:19:51
这篇文章提到了Threadlocal,NC里面就是用它来实现加锁及多线程操作 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。 各个线程中访问的是不同的对象。 另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。 通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。 如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 下面来看一个hibernate中典型的ThreadLocal的应用: Java代码 private static final ThreadLocal threadSession = new

[JavaEE]理解ThreadLocal

我的梦境 提交于 2020-02-04 18:19:25
转http://www.iteye.com/topic/103804 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。 各个线程中访问的是不同的对象。 另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。 通 过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行 ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作 为map的key来使用的。 如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 下面来看一个hibernate中典型的ThreadLocal的应用: Java代码 private static final ThreadLocal threadSession = new

ThreadLocal 源码分析

喜你入骨 提交于 2020-02-04 18:11:38
转自:http://www.iteye.com/topic/103804 首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。 各个线程中访问的是不同的对象。 另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。 通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作为map的key来使用的。 如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 下面来看一个hibernate中典型的ThreadLocal的应用: private static final ThreadLocal threadSession = new

ThreadLocal

你离开我真会死。 提交于 2020-02-04 18:10:22
首先,ThreadLocal 不是用来解决共享对象的多线程访问问题的,一般情况下,通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象,其他线程是不需要访问的,也访问不到的。 各个线程中访问的是不同的对象。 另外,说ThreadLocal使得各线程能够保持各自独立的一个对象,并不是通过ThreadLocal.set()来实现的,而是通过每个线程中的new 对象 的操作来创建的对象,每个线程创建一个,不是什么对象的拷贝或副本。 通 过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中,每个线程都有这样一个map,执行 ThreadLocal.get()时,各线程从自己的map中取出放进去的对象,因此取出来的是各自自己线程中的对象,ThreadLocal实例是作 为map的key来使用的。 如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象,那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身,还是有并发访问问题。 下面来看一个hibernate中典型的ThreadLocal的应用: Java代码 private static final ThreadLocal threadSession = new ThreadLocal(); public static