天天看點

多線程特性(原子性、可見性、有序性)多線程特性

多線程特性

原子性

​ 所謂原子性即:一個或者多個操作,要麼全部執行并且執行的過程不會被任何因素打斷,要麼就都不執行。

​ 在原子操作中,本質上拒絕多線程操作的,不論是單核或多核伺服器,當要對某一個資料進行原子操作時,同一時刻隻有有一個線程能夠對其進行操作,簡單來說,在整個操作過程中不會被線程排程器打斷,如a=1就是一個原子操作,但a++則不是一個原子操作,因為其内部會額外産生一個新的Integer對象。

​ 舉個例子,假設對一個32位的變量指派,操作分為兩步:低16位指派、高16位指派。當線程A對低16位資料寫入成功後,線程A被中斷。而此時另外的線程B去讀取a的值,那麼讀取到的就是錯誤的資料。

​ 在Java中的原子性操作包括:

基本類型的讀取和指派操作,且指派必須是數字指派給變量,變量之間的互相指派不是原子性操作。

所有引用的指派操作。

java.concurrent.Atomic.* 包中所有原子操作類的一切操作。

測試

public class test {
    public static void main(String[] args) throws InterruptedException {
        MyInt myInt = new MyInt();
        for(int i=0;i<2;i++){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    while (true){
                        System.out.println(Thread.currentThread().getName()+"----->"+myInt.getNum());
                        try {
                            Thread.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }

                }
            }).start();
        }
    }
    static  class MyInt{
        int num;
        public int getNum(){
          return   num++;
        }
    }
}
           
多線程特性(原子性、可見性、有序性)多線程特性

可見性

所謂可見性:即當多個線程通路同一個共享變量時,一個線程修改了該共享變量的值後,其他線程能夠立即檢視到修改後的值。

​ 在多線程環境下,一個線程對共享變量的操作對其他線程是預設是不可見的,也就是說一個線程對某一共享的修改,預設其他線程是無法進行檢視的。而如果要做到可見,Java中的volatile、synchronized、Lock都能保證可見性。如一個變量被volatile修飾後,表示當一個線程修改共享變量後,其會立即被更新到主記憶體中,其他線程讀取共享變量時,會直接從主記憶體中讀取。而synchronized和Lock能保證同一時刻隻有一個線程擷取鎖然後執行同步代碼,并且在釋放鎖之前會将對變量的修改重新整理到主存當中。是以可以保證可見性。

有序性

所謂有序性:即程式執行的順序會按照代碼的先後順序執行。

​ 其可以了解為在本線程内,所有的操作都是有序的。而如果在A線程中觀察B線程,所有的操作都是無序的。在JMM中為了提升程式的執行效率,允許編譯器和處理器對指令重排序。對于單線程來說,指令重排并不會産生問題,而在多線程下則不可以。

​ 在Java中可以通過synchronized和Lock來保證有序性,synchronized和Lock保證每個時刻是有一個線程執行同步代碼,相當于是讓線程順序執行同步代碼,自然就保證了有序性。

繼續閱讀