操做的原子性與線程安全

本案例來源於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

歡迎有興趣的童鞋一塊兒交流開發

相關文章
相關標籤/搜索