java多线程场景下如何保证静态变量list读取和更新不出错?
最近在写一个项目,在controller层中有一个变量public static List<String>list;
有一个接口是给前端返回这个变量值,有一个定时任务是定时更新这个值。
我应该怎么做才能保证更新的时候读取这个变量不出错?
注:这个接口是高频接口,不能每个人进来都加锁获取list,定时任务是几分钟跑一次。
目前已经想到的,更新的时候先新建一个新的变量newList,数据都放到newList中,最后让list指向newList,即list=newList,但不确定对象的赋值是否线程安全,即在赋值语句执行过程中,如果读取了list,会不会有异常情况?
回答:
题主的场景,使用线程安全的List不就可以了?java.util.concurrent.CopyOnWriteArrayList<E>
回答:
可以用 AtomicReference 包装一下。
回答:
这种场景明显就是读多写少,非常适合乐观锁使用啊,在读取数据时,允许多个线程并发访问,在写入时堵塞所有读取线程,直到写入成功。Java 自带乐观锁、悲观锁有StampedLock,当然ReadWriteLock也是可以处理这个场景的。
回答:
但不确定对象的赋值是否线程安全,即在赋值语句执行过程中,如果读取了list,会不会有异常情况?
a = b
是原子操作,没有线程安全问题,就这么实现就可以,可以考虑加一个volatile
回答:
首先,一般controller不应该写一些属性,这是一个不太好的习惯。可以简单的抽出来一个Util或者Manager啥的一个类,然后在里面去包含这个list。
然后,改完这部分代码之后,高频接口,要考虑为什么要用jvm去保存一个list;服务都是有多个的,使用jvm保存list,是否这个list就不存在多个服务的问题,这个也要思考清楚。
再然后,jvm的内存是一定的,高频访问的list也要考虑一下list存不存在多人同时塞数据导致OOM的情况,要评估一些数据规模以及占用的内存大小。一般来说,使用jvm保存一个数据来给外面访问而不是通过redis或者mysql拿到的数据返回出去,是为了做本地缓存,那么可以参考搜一些本地缓存的框架来实现。
最后,简单概况一些:
1,假设这个list一定要存jvm,那么CopyOnWriteArrayList的思路是可以实现的,因为这个集合读取是不会加锁的。
2,使用开源的框架EhCache、Caffeine等实现本地缓存的需求,支持更多复杂的特性
以上是 java多线程场景下如何保证静态变量list读取和更新不出错? 的全部内容, 来源链接: utcz.com/p/944628.html