赞
踩
当多个线程同时访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那就称这个对象是线程安全的
可以将Java语言中各种操作共享的数据分为以下五类:不可变、绝对线程安全、相对线程安全、线程兼容和线程对立
CAS指令需要有三个操作数,分别是内存位置(在Java中可以简单地理解为变量的内存地址,用V表示)、旧的预期值(用A表示)和准备设置的新值(用B表示)。CAS指令执行时,当且仅当V符合A时,处理器才会用B更新V的值,否则它就不执行更新。上述的处理过程是一个原子操作
如适应性自旋、锁消除、锁粗化、轻量级锁、偏向锁等
ThreadLocal本质是变量 ,它为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 每个线程都有一个map,类似于context,用于存储每一个线程的变量副本。既然是map,key就是ThreadLocal名,value就是变量副本。
ThreadLocal和线程同步机制都是为了解决多线程中相同变量的访问冲突问题, 同步机制采用了“以时间换空间”的方式,而ThreadLocal采用了“以空间换时间”的方式。在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量,这时该变量是多个线程共享的, 程序设计和编写难度相对较大 。ThreadLocal会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。
线程里面会有一个context,即上下文,可以往context里面存放东西,随后在线程管辖范围内都可以获取到。ThreadLocal在set存数据到线程context的时候,把自己(this)也放进去
内存泄漏就是东西放在内存里面,但你忘记它放哪里了,它占着一块内存,但是不能回收。 ThreadLocal作为key,存入ThreadLocalMap里面,但是因为key被包装成弱引用,很容易导致内存泄漏 。
//声明一个ThreadLocal变量b,此时开辟了一块内存,里面存放的b对象
ThreadLocal<Integer> b = new ThreadLocal<Integer>();
//注意,这里不是赋值,赋值是=操作符
b.set(10)
(1)10不是放在了b里面,10和b是两个独立存放的东西,不是包含关系。
(2)10和b是两个独立存放的变量,如果其中的一个被清理,那么另外一个不受影响的。
10和b两个的独立存放的东西,只不过我们不能直接访问到10,必须通过b来传话,原因很简单,在map里面,value要通过key来访问。
不过,此时b被包装成了弱引用,也就是说它被打了一个标签,这样它很容易被gc。一旦b被清理了,10就找不到了,从而造成了内存泄漏。
(1)有两个变量a和b,如果后面不再参与计算,则会被自动回收;
(2)有两个变量a和b,存放在map里面,a是key,b是value。如果map一直存在,a和b因为被map关联,则a和b就一直不能被回收;
(3)有两个变量a和b,存放在map里面,a是key(但是a被弱引用包装了一下),b是value。如果map一直存在,a和b因为被map关联,则b就一直不能被回收,但是a可以被回收。一旦a回收了,那么无法通过a找到b了,这就是b出现内存泄漏。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。