ConcurrentHashMapJava

ConcurrentHashMapJava,java,concurrency,Java,Concurrency,这似乎是错误的 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.a=#),而不在“o”或“k”上同步,会发生什么 简单地说: o.a=6 是一个原子操作,所有线程都将竞争,最后一个线程设置它将“赢”,覆

这似乎是错误的

        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.a=#),而不在“o”或“k”上同步,会发生什么

简单地说:

  o.a=6
是一个原子操作,所有线程都将竞争,最后一个线程设置它将“赢”,覆盖该值

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


这不会阻止任何线程在获得对该值的引用后修改该值的属性

ConcurrentHashMap保证获取值是原子的,但它无法控制如何处理从中获取的值。从ConcurrentHashMap的角度来看,修改hashmap中的值是可以的,但可能仍然不会产生您想要的行为。要确保线程安全,您需要准确地考虑每个线程对它的访问权限。

将该值放回ConcurrentHashMap似乎是多余的,不会使整个操作更加安全。您已经在任何同步之外修改了对象


额外的同步可能是必要的,但如果没有更多的上下文,我无法确定。ConcurrentMap有条件操作,可以保证原子插入/删除和替换键/值对。此外,访问ConcurrentMap会创建一种关系,这样您就可以确保代码的顺序

在给出的代码中,行:

X o = k.get("LL");
访问键“LL”的当前X值。下一行修改a属性。不知道X的实现,这是Java,所以我们知道这里没有方法调用。如果(且仅当)a属性被标记为volatile,那么在“LL”处访问X的后续代码将看到a值为6。如果它不是易变的,那么就没有任何保证。他们可能会看到6,特别是在SMP x86机器上,没有多少线程同时做很多事情。在生产中,在一个大的NUMA盒子上,他们不太可能。易变性带来了各种各样的复杂性和困难


通常,如果使用不可变的键和值,您会发现更容易推断映射所处的状态。

我相信(是的,我不确定)当您尝试从X对象设置a属性时,在运行时会引发异常。那么同步(o){o.a=6;}?@SamAdams这意味着您可以100%确定整个同步块中
o.a
的值为
6
。为了更好地解释,concurrenthashmap仅保证键与其关联值之间的链接在处理时考虑多个线程。它不会阻止您在获得对该值的引用后修改该值的属性。没有任何迹象表明该值是“原子的”,或者设置该值时有任何内存保证。事实上,在“最后一个线程设置它”的语句中没有任何意义,因为线程之间没有按时协商。很有可能几个不同的线程使用同一个o,并且所有线程都具有完全不同的o.a值。它仍然不是原子的,volatile只为您提供可视性保证;第3行:synchronized(k){x=k.get(“LL”);}第12行:synchronized(k){x.a++}第一个线程经过第3行,第二个线程经过第3行当线程1在第5行时,第一个线程改变x.a,然后第二个线程改变x.a,会发生什么情况?唯一的方法是(++x.a两次)重置第12行中的x:synchronized(k){x=k.get(“LL”);x.a++}?@SamAdams在这两个示例中,x将增加两次。但是如果没有同步块,其中一个更新可能已丢失。对于读取:x x;第3行:同步(k){x=k.get(“LL”);}第12行:同步(k){if(x.b){x.b=false;}第一个线程通过第3行,第二个线程通过第3行,当线程1位于第5行时,线程1将x.b更改为false,线程2看到了什么x.b?我将在另一个问题中问这个问题。访问如何创建一个发生在javadoc之前的事件,表示发生在写入/添加之前的事件。那么,文档状态“在将对象放入任何并发集合之前,线程中的操作发生在另一个线程的集合中访问或移除该元素之后的操作之前。“因此,您是正确的,不能保证对可变值的写入必然会在并发集合中访问相同的值。正如Rich Hickey所说,我们发明了可变价值,我们应该取消它们。