1. 程式人生 > >原子操作組合與執行緒安全

原子操作組合與執行緒安全

public class TestTwoAtomicMethods {
	private final ConcurrentHashMap<Integer,Integer>  map = new  ConcurrentHashMap<Integer,Integer>();
	@Interleave
	public void update()  {
			Integer result = map.get(1);		
			if( result == null )  {
				map.put(1, 1);
			}
			else	{
				map.put(1, result + 1 );
			}	
	}
	@Test
	public void testUpdate() throws InterruptedException	{
		Thread first  = new Thread( () -> { update();   }  );
		Thread second = new Thread( () -> { update();   }  );
		first.start();
		second.start();
		first.join();
		second.join();
		
	}	
	@After
	public void checkResult() {
		assertEquals( 2 , map.get(1).intValue() );
	}	
}

下面是控制檯列印資訊: 至於為什麼會這樣的,原因是因為在代理第5行執行完之後,在下面複製的判斷過程中依然存在著多個執行緒同時進去if-else判斷的可能性,藉助vmlens這個外掛,能夠很明顯看到原因,圖如下:

圖中可以看到在執行ConcurrentHashMap的原子操作get和put方法時候,出現了執行緒間的競爭,13和14執行緒分別先獲取到了物件的鎖,然後取得了map.get(1)的值,此時值為null,兩個執行緒的取值都是null,剩下的就比較明瞭了。兩個執行緒都進入了if-else判斷的第一個條件語句中,又先後複製map.put(1,1),這樣最終的結果map.get(1).intValue()就等於1,斷言失敗。

歡迎有興趣的