本案例來源於java zone社區,因爲源代碼裏面存在一些本身開發的註解,我暫時沒找到相關的文檔,因此我作了一些修改。用的都是java SDK的API。 關於概念:java
原子性:即一個操做或者多個操做 要麼所有執行而且執行的過程不會被任何因素打斷,要麼就都不執行。git
線程安全:就是多線程訪問時,採用了加鎖機制,當一個線程訪問該類的某個數據時,進行保護,其餘線程不能進行訪問直到該線程讀取完,其餘線程纔可以使用。不會出現數據不一致或者數據污染。api
線程不安全:就是不提供數據訪問保護,有可能出現多個線程前後更改數據形成所獲得的數據是髒數據安全
進入正題,若是能夠從多個線程調用全部方法而沒有外部同步,則類是線程安全的。爲了實現這一點,線程安全方法必須是原子的,例如,其餘線程只能看到方法以前或以後調用之間的狀態。如下示例說明了爲何線程安全方法必須是原子的:markdown
public class TR extends FanLibrary { private volatile int i = 0; public void ss() { sleep(100);//爲了更容易出現效果 i++; } @Before public void be() { output("before"); } @Test public void sdfa() throws InterruptedException { Thread first = new Thread(() -> { ss(); }); Thread second = new Thread(() -> { ss(); }); first.start(); second.start(); first.join(); second.join(); output(i); } @After public void ds() { output("after"); } }
控制檯輸出,如下內容可能會出現,代碼中sleep(100)的緣由:多線程
INFO-> before INFO-> 1 INFO-> after
其中「i++;」至關於「i = i + 1;」包含了「i + 1」和「i =」兩個過程,不屬於原子操做,因此在多線程訪問該方法的時候是不安全的線程
當兩個線程同時獲取到i = 0的值時,若是此時都沒有執行到「i =」這個步驟的時候,那麼兩個線程等號右邊都是1,而後先後執行「i = 1」 這個操做,至關於i最終被兩次賦值爲1,因此最終「i = 1」code