Java并发
2021-09-14 20:47:36 9 举报
AI智能生成
Java并发 相关知识整理
作者其他创作
大纲/内容
ThreadLocal适用于变量在线程间隔离,在方法或者类间共享的场景
介绍
使用ThreadLocal存放用户信息,有使用获取到的用户信息是别人的
场景
ThreadLocal采用的是Map的结构进行存储。程序一般运行在Tomcat上,Tomcat基于线程池进行工作的。所以一般会进行线程重用,一旦重用就有可能获取到的值是上次线程保存的值。
问题
使用ThreadLocal工具进行数据存放时,在代码运行完成时,显示清空设置的数据。
在请求的一开始就进行设值,后面获取到的也会是该值
解决方式
ThreadLocal
是一个高性能的线程安全的哈希表容器。ConcurrentHashMap是保证提供的原子读写操作时线程安全的,但是两个操作顺序执行就不是原子操作了
这是两个操作并不保证原子性
如果需要保证原子性,需要在这两次操作进行加锁逻辑
putAll 这样的聚合方法也不能确保原子性,在 putAll 的过程中去获取数据可能会获取到部分数据。
先查询map的size() 然后调用 put()
computeIfAbsent 来做复合逻辑操作,判断Key是否存在Value,如果不存在就把Lambda表达式运行后的结果放入Map作为Value,创建一个LongAdder对象最后返回Value。LongAdder是一个线程安全的累加器,可以直接调用increment()方法进行累加
一些原子操作的方法,Java在底层实现了CAS,在虚拟机层面确保写入数据的原子性,比加锁的效率高很多
提供了一些原子性的简单复合逻辑方法
ConcurrentHashMap
线程安全的ArrayList,实现方式每次修改数据都会复制以分数出来,适用于读多写少希望无锁读的场景
修改更新数据都会Arrays.copyOf创建一个新数组,频繁修改时,申请内存释放会消耗很大
设置、新增、删除都需要 重新拷贝一份新的数组,这样的好处就是读不会阻塞读,但是会消耗一定的内存,拷贝数组会花费时间
使用ReentrantLock可重入锁控制加锁和解锁逻辑
迭代器提供支持一些常用的方法,不支持remove、set、add操作
CopyOnWriteArrayList
静态字段属于类,累计被的锁才能保护
非静态的字段属于实例,实例级别的锁可以保护
1. 通常情况下60%的业务代码时三层架构,数据经过都是无状态的, 没有必要保护数据
2. 极大影响性能,使用Spring框架时,默认情况下Controller、Service、Repository是单例的,加上synchronized只会导致程序只支持单线程,造成极大的性能问题
确实有一些共享资源需要保护时,尽可能降低锁粒度,仅对必要的代码块或者保护的资源本身加索
滥用synchronized
锁对象还是锁类
并发
收藏
收藏
0 条评论
下一页