BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #64275同步于 2020/8/19
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

求教关于map的一个可见性的问题

cc19931002
2020/8/19镜像同步20 回复
如果是简单的HashMap<String, Peopele>,一个线程你会定期读取这个map中的数据,另外一个线程会定期的更新这个map中的数据,更新的操作是修改这个map中某些People的字段(比如年纪等等),这种场景下会有可见性问题吗? 如果存在换成并发Map还会存在可见性问题吗? 如果依然存在那怎样才能避免可见性问题呢?
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
wwj1204机器人#1 · 2020/8/19
建议详细说一下这里 可见性 的范围?是people的某个字段?单个people?还是一组people? 解决方案可以考虑copyonwrite的思想 【 在 cc19931002 (啦啦) 的大作中提到: 】 : 如果是简单的HashMap<String, Peopele>,一个线程你会定期读取这个map中的数据,另外一个线程会定期的更新这个map中的数据,更新的操作是修改这个map中某些People的字段(比如年纪等等),这种场景下会有可见性问题吗? : 如果存在换成并发Map还会存在可见性问题吗? : 如果依然存在那怎样才能避免可见性问题呢? : ...................
a2012210456机器人#2 · 2020/8/19
感觉一个线程只读一个线程只写的话应该不会有问题吧?等大神解答 【 在 cc19931002 (啦啦) 的大作中提到: 】 : 如果是简单的HashMap<String, Peopele>,一个线程你会定期读取这个map中的数据,另外一个线程会定期的更新这个map中的数据,更新的操作是修改这个map中某些People的字段(比如年纪等等),这种场景下会有可见性问题吗? : 如果存在换成并发Map还会存在可见性问题吗? : 如果依然存在那怎样才能避免可见性问题呢? : ...................
root0439机器人#3 · 2020/8/19
换成并发map肯定没问题,people的字段是volitale的么?如果是volitale,单纯的读写没有问题,如果这个字段需要用于逻辑判断肯定是存在问题的 【 在 a2012210456 (asdqo) 的大作中提到: 】 : 感觉一个线程只读一个线程只写的话应该不会有问题吧?等大神解答
wangzhigang机器人#4 · 2020/8/19
普通的hashmap是线程不安全的,多线程请用concurrentHashMap,可以了解一下 JMM,Java线程内存模型,对这个问题就比较清晰了
hkd机器人#5 · 2020/8/19
hashMap单线程下没问题,多线程下线程不安全,得用并发包下的map
qq916545028机器人#6 · 2020/8/20
并发map解决的是并发读取的问题,防止读时删或者加导致读取People错误。 但是修改People字段本身也是需要原子操作化的,比如一个int,你需要了解底层是按照8bit拷贝还是16bit拷贝(一般是16),比如一个string,肯定是一个字符一个字符拷贝的。那么你在读取一个People后,修改这个People的一个字段,另一个线程读取这个People,在并发map是可行的(并发读),但是后者拿到的对应字段可能是写到半中间的情况,导致读取脏数据。因此会存在可见性问题。 解决方案,copyonwrite。拷贝一个People,做修改,然后原子操作替换map中的People对象引用
duanyf机器人#7 · 2020/8/20
可以把people类所需要修改的属性,加上Volitale,并且在修改这个字段的set方法上加sync修饰。这样可以保证并发安全。。就类似concurrenthashmap了。
wwj1204机器人#8 · 2020/8/20
单纯方法上加加sync的话,所有的people对象加了sync的set方法都会竞争同一个锁(加sync默认锁为当前class对象)。加sync的话,可以考虑每个set方法里面加,锁为要set的字段 【 在 duanyf (小呆不发呆) 的大作中提到: 】 : 可以把people类所需要修改的属性,加上Volitale,并且在修改这个字段的set方法上加sync修饰。这样可以保证并发安全。。就类似concurrenthashmap了。
csxiaoshang机器人#9 · 2020/8/20
我理解ConcurrentHashMap在一定程度上是可见的,java8的ConcurrentHashMap在put的时候,当table[]的相应位置为空时,使用cas设置值;若table[]相应为位置不为空,则使用syncrinized设置值。cas不保证可见性,syncrinized保证可见性。