這似乎是錯誤的。concurrenthashmap java
static ConcurrentHashMap k; //multiple threads have access to k
X o = k.get("LL");
o.a = 6;
如果多個線程訪問類型k同時,並得到K( 「LL」),則更新(OA =#),而不k.put( 「LL」,○),而對 'O' 同步,或'k'會發生什麼?
這似乎是錯誤的。concurrenthashmap java
static ConcurrentHashMap k; //multiple threads have access to k
X o = k.get("LL");
o.a = 6;
如果多個線程訪問類型k同時,並得到K( 「LL」),則更新(OA =#),而不k.put( 「LL」,○),而對 'O' 同步,或'k'會發生什麼?
ConcurrentMap具有保證原子插入/移除和鍵/值對替換的條件操作。此外,訪問ConcurrentMap會創建一個happens-before關係,因此您可以對代碼的排序作出一定的保證。
在代碼呈現,行:
X o = k.get("LL");
訪問當前X值的鍵 「LL」。下一行修改一個屬性。不知道X的實現,這是Java,所以我們知道這裏沒有方法調用。 如果(且只有)某個屬性被標記爲易失性,那麼在「LL」處訪問X的後續代碼將看到一個值爲6.如果它不是易失性的,那麼根本沒有保證。他們可能會看到6,特別是在SMP x86機器上,當時沒有太多的線程在做很多事情。在生產中,在一個大的NUMA盒子裏,他們不太可能。可變性帶來了各種各樣的困難和複雜性。
通常,如果使用不可變的鍵AND值,則會更容易推斷映射所處的狀態。
如何訪問創建一個發生 - 之前,javadoc,說發生 - 之前是寫/添加。 –
好吧,文檔狀態「行動在一個線程在將對象放入任何併發集合之前發生 - 在從anot中訪問或從集合中移除該元素之後的動作之前她的線程「。所以你是正確的,不能保證寫入一個可變值將必然揹負只是在併發集合中訪問相同的值。正如Rich Hickey所說,我們發明了可變的價值觀,我們不應該試探它們。 –
簡單地說:
o.a=6
是一個原子操作,所有的線程會競爭,最後一個線程設置將「贏」,覆蓋值。
更具體地說,ConcurrentHashMap只保證在考慮多個線程的情況下處理關鍵字與其關聯值之間的鏈接 - 即put和get是原子。
這並不妨礙任何線程在獲取對它的引用後修改該值的屬性!
同步(o){o.a = 6;}? –
@SamAdams,這意味着你可以100%確定在整個同步塊中o.a的值是'6'。 – MarioDS
它取決於 - o.a = 6是由主線程執行的,所以不能保證其他線程在之後不會修改該值。 – thedayofcondor
ConcurrentHashMap保證獲取一個值是原子的,但它不能控制你對它的值做什麼。修改hashmap中的值在ConcurrentHashMap的視圖中沒有問題,但可能仍然不會導致您想要的行爲。爲了確保線程安全,您需要確切地考慮每個有權訪問它的線程。
將數值放回到ConcurrentHashMap中似乎是多餘的,並且不會使整個操作更安全。您已經在任何同步之外修改對象。
額外的同步可能是必要的,但我不能確定沒有看到更多的上下文。
X x;第3行:synchronized(k){x = k.get(「LL」);}第12行:synchronized(k){x.a ++;}第一個線程通過第3行,第二個線程通過第3行在第5行,線程1改變了xa,然後線程2改變了xa,會發生什麼? –
是唯一的方法來做到這一點(++ xa兩次),重置第12行中的x:synchronized(k){x = k.get(「LL」; x.a ++}? –
@SamAdams在這兩個示例中,x如果沒有同步塊,則其中一個更新可能已經丟失。 – fgb
我相信(是的,我不知道)A併發修改例外(http://docs.oracle.com/javase/7/docs/api/java/util/ConcurrentModificationException.html)異常將提高在運行時嘗試從X對象設置屬性。 –