Moosphan / Android-Daily-Interview

:pushpin:每工作日更新一道 Android 面试题,小聚成河,大聚成江,共勉之~

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

2020-03-03:说说ThreadLocal的使用场景?与Synchronized相比有什么特性?

Moosphan opened this issue · comments

commented

ThreadLocal和Synchronized虽然都和多线程有关.
但是ThreadLocal是为了多线程时,每个线程对变量的独立访问.线程间该变量值互不影响.内部是由一个ThreadLocalMap,key为当前ThreadLocal的弱引用,value为变量值.
Synchronized则是另一个意思.多线程时通过同步锁实现多个线程同时只能有一个线程对变量/方法访问.

ThreadLocal的应用场景是:当多个线程访问同一个类的变量,但是又不想共享,只想在自己的的线程中使用,那么ThreadLocal就能实现把变量从线程中隔离的作用

Synchronized是保证同一时刻只有一个线程能访问对象,对象是共享的

ThreadLocal 是一个线程内部的数据存储类。通过它可以指定线程中存储的数据,只有指定的线程才可以读取到数据,对应其他线程是无法拿到数据的
https://blog.csdn.net/baidu_40389775/article/details/86759882

commented

线程安全有三种类别:
1,互斥同步,也就是你说的Synchronized关键字,还有Lock机制,原理是通过保证在同一个时刻只有当前线程能够对这部分内存进行修改。
2,CAS同步,这种策略是记录先前的量,然后尝试修改,修改完成,若标志量没有变化,则认为是线程安全的。例如典型的CAS操作。当然, 它存在ABA问题
3,可重入代码和线程私有内存,这种是天然的线程安全。线程安全的本质是多线程之间主内存同步的问题。而线程私有内存,多个线程之间就不存在内存冲突,当然就没有线程安全问题。ThreadLocal就是这种。

使用场景:看源码里面,以Thread作为key,那么Thread数量较多且有交互的情况就很合适。例如:线程池的线程独立内容管理。

ThreadLocal是数据存储类,内部有一个ThreadLocalMap类,Thread持有ThreadLocalMap类型的变量,使用ThreadLocal存储数据时,其实是将数据存储到当前Thread的ThreadLocalMap变量里面,
ThreadLocalMap里面有一个数组,每创建一个ThreadLocal类是都会计算出一个唯一的数组下标【i】,当存储数据时就会将数据存在Thread的ThreadLocalMap变量的数组里,以【i】为下标,所以使用ThreadLocal存储数据其实是将数据存在了线程的私有内存里面,就不会存在线程安全问题。
Synchronized是通过互斥机制来保证同一时间只有一个线程拿到当前变量。

就使用场景而言:
ThreadLocal在android的Looper和ActivityThread里面有使用到,如果数据以线程为作用域,也就是数据和线程强绑定,那么就可以使用ThreadLocal
Synchronized是为了保证主内存的同步,此时并不需要每个线程都保存一份数据

注: 所以上面几个回复中所有【以Thread作为key】的说法全是错的。

前面说Thread作为key是错误的 ,ThreadLocal才是key, 该key虽然是个弱引用, 但是还是会存在内存泄漏的风险, 使用完后remove掉才可以避免出现内存泄漏