原子作業
早期物理學認為原子是構成宇宙萬物的最小單位,無法繼續分割。所以原子作業是指單一個操作,具有不可中斷的意思。
比如 a=10 屬原子作業,因為組合語言會翻譯為
mov a, 10
以上是一個指令,不可能執行到一半就被中斷。但如果是 i++,則不屬原子作業,因為組合語言會翻譯成 3 個指令
mov eax,【xxxxxxxx】 inc eax mov 【xxxxxxxx】, eax
即然被編譯成三個指令,就有可能中途被中斷,所以不是原子作業。
組合語言並沒有原子作業
組合語言其實並沒有原子作業,因為你下達什麼指令它就作什麼事,笨的很。原子作業是一連串的演算法所規範,由C語言來規定的。
C 語言也沒有原子作業
C 語言是所有語言的鼻祖,但 C 也沒有原子作業,通常需藉助第三方的執行緒庫,如 intel 的 pthread 來實現。從 C11 開始引入原子操作的概念,標頭檔提供多種原子運算元數據型別,如 atomic_bool、atomic_int 等。如果我們在多個執行緒中共享這些型別資料,編譯器將保證這些指令都是原子作業。也就是說確保任意時刻只有一個執行緒能對這個資源進行訪問。編譯器保證多個執行緒訪問這個共享資源絕對正確。
Java原子作業
二個或以上的執行緒存取物件變數時,情況就會變的很複雜。
Java 使用 synchronized 實作了C11 的 pthread 函數庫,確保 synchrnoized 區塊內的程式碼在執行完成前不被其他執行緒所干擾。
為了保證某一段程式碼能在目前執行緒完成作業前不會被其他執行緒重複執行,這就是同步作業(Synchronized)
volatile [ˋvɑlət!]
在變數前加上volatile修飾子, 如
volatile int a=10;
此即告訴 JVM 此變數是不穩定的,所以當線程訪問時, 就會強迫從共用記憶体區重新取得該變數的值, 讓所有的線程看到的值都是同一個, 所以使用volatile會很耗費資源
但此修飾子只保証執行緒寫回記憶体這段是同步, 但不保証只有一個執行緒在存取這個值, 所以仍有其風險
共同作業與共競
先看下面的代碼
新Thread與UI元件
SwingUtilities.invokeLater(new Runnable() {
public void run() {
progressBar.setValue(i);
}
});
