concurrenthashmap java

3

这看起来不对。

        static ConcurrentHashMap k; //multiple threads have access to k
         X o = k.get("LL");
         o.a = 6;

如果多个线程同时访问k,并获得k("LL"),然后在不使用k.put("ll",o)、不在'o'或'k'上同步的情况下更新(o.a = #),会发生什么?

我认为(是的,我不确定)当您尝试从X对象设置属性时,运行时会引发并发修改异常异常。 - Bruno Vieira
3个回答

2
ConcurrentHashMap保证获取值是原子的,但无法控制您从中获取的值的使用方式。从ConcurrentHashMap的视角修改哈希映射表中的值是可以的,但仍然可能导致您不想要的行为。要确保线程安全,需要考虑每个访问它的线程实际执行的操作。
将值放回ConcurrentHashMap似乎是多余的,并不会使整个操作更加安全。您已经在任何同步之外修改了对象。
可能需要额外的同步,但如果没有看到更多上下文我无法确定。

X x; 第3行:synchronized(k){ x = k.get("LL");} 第12行:synchronized(k){x.a++;} 当第一个线程执行第3行时,第二个线程在第1个线程执行第5行时执行第3行,然后第一个线程更改了x.a,接着第二个线程也更改了x.a,会发生什么? - Sam Adamsh
这个问题的唯一解决方法 (++x.a 两次) 是在第12行重置 x: synchronized(k){x = k.get("LL); x.a++} 吗? - Sam Adamsh
@SamAdams 在这两个例子中,x都会被增加两次。但是如果你没有同步块,其中一个更新可能会丢失。 - fgb
对于读取:X x; 第3行:synchronized(k){ x = k.get("LL");} 第12行:synchronized(k){if(x.b){x.b = false;}} 当第一个线程通过第3行时,第二个线程在第一个线程在第5行时通过第3行,第一个线程将x.b更改为false,第二个线程看到的x.b是什么-我会在另一个问题中问这个。 - Sam Adamsh

2

ConcurrentMap具有条件操作,可以保证对键/值对的原子插入/删除和替换。此外,访问ConcurrentMap会创建happens-before关系,因此您可以对代码的排序作出一定的保证。

在呈现的代码中,该行:

X o = k.get("LL");

访问键“LL”的当前X值。下一行修改a属性。不知道X的实现情况,但这是Java,我们知道这里没有方法调用。如果a属性被标记为易失性,则访问“LL”处的X的某些后续代码将把a值视为6。如果它不是易失性的,则根本没有保证。他们可能会看到6,特别是在SMP x86盒子上,当时没有多少线程在做任何事情。在生产环境中,在大型NUMA盒子上,它们不太可能出现。可变性带来了各种复杂性和困难。

通常,如果使用不可变的键和值,则更容易理解映射所处的状态。


访问如何创建 happens-before,javadoc 表示 happens-before 用于写入/添加。 - Sam Adamsh
嗯,文档中指出:“在将对象放入任何并发集合之前的线程操作会先于在另一个线程中访问或移除该元素的操作。”所以你说得对,对可变值的写入并不能保证一定会通过并发集合中相同值的访问来实现。正如Rich Hickey所说,我们发明了可变值,我们应该取消它们的发明。 - Jed Wesley-Smith

1

简单来说:

  o.a=6

是一个原子操作,所有线程都会竞争,最后一个设置它的线程将“获胜”,覆盖该值。

更具体地说,ConcurrentHashMap仅保证处理键和其关联值之间的链接时考虑多个线程 - 即put和get是原子的

这并不防止任何线程在获取对其的引用后修改值的属性!


那么synchronized(o){o.a = 6;}怎么样? - Sam Adamsh
2
@SamAdams 这意味着在整个同步块中,您可以100%确定o.a的值为6 - MarioDS
2
为了更好地解释,ConcurrentHashMap 仅保证在考虑多个线程时处理键和其关联值之间的链接。它不能防止您在获取对值的引用后修改值的属性。 - thedayofcondor
1
没有任何迹象表明这是“原子性”的,也没有任何内存保证来设置它。事实上,在语句“最后一个线程设置它”中,如果没有happens-before,就没有意义,因为线程之间没有时间协商。很可能有几个不同的线程正在使用相同的o,并且所有线程都具有完全不同的o.a值。 - Jed Wesley-Smith
1
它仍然不是原子性的,volatile 只能给你可见性保证。 - Jed Wesley-Smith
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接