關鍵字的作用
摘自JDK 1.8
同步方法支持一種簡單的策略來防止線程干擾h和內存一致性錯誤:如果一個對象對多個線程可見,則對該對象變量的所有讀取或寫入都是通過同步方法完成的。
通俗易懂的
能夠保證在同一時刻最多隻有一個線程在執行該段代碼,以達到確保併發安全的效果。
地位
- 作爲關鍵字,被Java語言原生支持
- 是最基本的同步手段
- 是併發編程的元老級角色,併發編程的必學內容
不使用併發的後果
一段非常簡單的代碼
public class DisappearRequest1 implements Runnable {
static DisappearRequest1 instance = new DisappearRequest1();
static int i = 0;
public static void main(String[] args) throws InterruptedException{
Thread t1 = new Thread(instance);
Thread t2 = new Thread(instance);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println(i);
}
@Override
public void run() {
for(int j=0; j<100000; j++) {
i++;
}
}
}
join()是Thread類的一個方法。根據jdk文檔的定義:
public final void join()throws InterruptedException: Waits for this thread to die.
join()方法的作用,是等待這個線程結束;但顯然,這樣的定義並不清晰。
個人認爲"Java 7 Concurrency Cookbook"的定義較爲清晰:
join() method suspends the execution of the calling thread until the object called finishes its execution.
也就是說,t.join()方法阻塞調用此方法的線程(calling thread),直到線程t完成,此線程再繼續;通常用於在main()主線程內,等待其它線程完成再結束main()主線程。
輸出結果自然是遠遠小於200000,基本很少超過160000。原因就是i++這個動作在底層是分成3步來做的
- 從內存中讀取i
- i++
- 寫入內存
如果不控制併發,那麼i的值就會被前一個被爭奪走資源的線程在拿到CPU資源使把i“變小”(相當於後一個線程的對i加的循環沒有作用了)
以上這種情況就是我們說的線程不安全