001-线程间的通信、协作、隔离

线程间的通信和协作

synchronize

volatile

保证了不同线程对变量进行操作的可见性
如静态变量
不加关键字则子线程无法感知主线程变更
加了就能感知到主线程对静态变量的修改
使用场景:一个线程写,多个线程读

等待/通知机制

单纯的轮询耗费性能,单机情况下可以使用等待通知机制实现
wait() 和 notifyAll() 两个方法必须放在同步方法中或者同步块中
角色:

  • 等待方
  • 通知方

等待方:

sybchronized (对象) {
	while (条件不满足) {
		对象.wait();
		//此时释放锁,线程进入等待
	}
}

通知方:

sybchronized (对象) {
	业务处理;
	对象.notifyAll();
}

ThreadLocal

什么用

是什么:当前线程数据副本
什么用:跨方法参数传递

实现

ThreadLocalMap

考虑到性能问题 数据副本每个线程自己持有最快
每个线程初始化的时候 创建一个ThreadLocalMap
Map中的每个Entry 的key 是 ThreadLocal, value是存入的值

下图是一个将ThreadLocal声明为静态变量的内存对象模型图
实线箭头是:强引用
虚线箭头是:弱引用
在这里插入图片描述

属于这个线程的ThreadLocal值。这个映射由ThreadLocal类维护。
在这里插入图片描述
ThreadLocal中set()的时候 获取map 如果没有则创建
在这里插入图片描述
在这里插入图片描述
首次懒加载Map
在这里插入图片描述

数据副本

这里的数据副本不是说会对对象进行复制还是什么其他操作
这里的副本就是 set(Object value) 的value 本身
所以在使用 ThreadLocal 的时候 内容需要在线程中自己创建 或者在 initialValue()中创建
如果设置一个公共的变量 那么隔离机制会被打破

Hash冲突

开发地址法:线性探测
如果存储的时候hash位置被占用 则依次往下找空位

从计算出来的hash 作为索引i开始 如果table[i]内容 e 不为空
则 判断:
如果 e 等于 传入的ThreadLocal 则 替换值
如果 e 为 null 则重新刷新 Entry *(1)
当For循环 执行完还没有跳出的话 i 的值就是 第一个空的位置
直接塞进 table即可
在这里插入图片描述
这里就是简单的判断如果 i小于长度 -1 则返回 i+1 否则就是到尾部了 直接从 0 开始
在这里插入图片描述
(1) 为什么有Entry不为空 其中的key为空呢?
因为key 用的软引用,下边内存泄漏有解释

(2) 那会不会出现所有槽位都已经插满了内容而无法处理hash冲突了
默认的容量是16
每次插入内容会判断一下是否 size已经大于容量的3/4了
如果大于则 容量 * 2扩容
在这里插入图片描述

内存泄漏

局部变量的生命周期应该是同方法一致
但是ThreadLocal是绑定在线程上的
存放的局部变量生命周期可能和线程一致
而线程池中的线程长期存活
就会造成内存泄漏

本质是
就算方法执行完毕 ThreadLocal对象因为局部变量的出栈
也就entry的key无用了 再GC时候会直接清理(弱引用)
但是entry 的 value 还在引用 但是无法访问了

引用链:Thead -> ThradLocalMap -> Entry[] -> entry -> value

所以:ThreadLocal 必须 remove()

为什么使用弱引用

如果不用弱引用
则用户没有手动remove() 的情况下 Entry中的key 也会产生内存泄漏

为什么使用弱引用再GC的时候没有问题

一般我们使用ThreadLocal创建静态变量直接new出来
虽然ThreadLocalMap中对ThreadLocal引用是弱引用
但是直接new出来的部分是强引用
保证ThreadLocal不会被清除
在这里插入图片描述
就算是成员变量
在方法还未出栈的时候ThreadLocal由对象强引用
所以仍不会被销毁

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值