執行緒第六課——同步鎖synchronized
阿新 • • 發佈:2018-11-28
這節課我們來講講同步鎖synchronized
先來說說為什麼要有這個玩意。多執行緒在併發訪問共享資源時可能會引發安全問題(上節課演示過了),為此我們需要在某一個執行緒訪問共享資源時拒絕讓其他執行緒繼續訪問。
舉個例子,廁所是公共資源吧,每個人就是一個執行緒,當一個人使用一個廁所的時候是不是要在自己使用期間阻止其他人使用?那麼怎麼阻止?把門鎖上即可。這把鎖就是我們今天要講的synchronized
public class SynchronizedTeach { public static void main(String[] args) { MineThread thread1 = new MineThread(); MineThread thread2 = new MineThread(); thread1.start(); thread2.start(); while (true) { if (thread1.getState() == Thread.State.TERMINATED && thread2.getState() == Thread.State.TERMINATED) { System.out.println(MineThread.i.get()); break; } } /** * 在沒有枷鎖的情況下 如預料般的結果出錯了 * 下面說下synchronized可以加在哪裡: * 1. 普通方法上,上鎖的是當前物件 * 相當於在方法裡寫synchronized(this) * 2. 靜態方法上,上說的是這個類的Class物件 * 相當於在方法裡寫synchronized(this.getClass())或者synchronized(本類.class) * 3. (普通/靜態)方法裡寫 * synchronized(obj){ * 需要上鎖的程式碼 * } * obj是要被鎖的物件 */ } } //自己寫個執行緒吧 class MineThread extends Thread{ public static Int i = new Int(0); public MineThread() { } public MineThread(Runnable target) { super(target); } public MineThread(String name) { super(name); } public MineThread(Runnable target, String name) { super(target, name); } /* 當synchronized被放在方法上時,鎖的是當前物件(也就是this),但是i是靜態成員,鎖當前物件是鎖不住的 @Override public synchronized void run() { for (int j = 0; j < 4000; j++) { i.add(); } } */ /* 這次鎖的物件是靜態成員i,在操作i時對i上鎖了,其他執行緒就無法在該執行緒訪問i期間訪問i,所以不會引發安全問題 @Override public void run() { for (int j = 0; j < 4000; j++) { synchronized (i) { i.add(); } } } */ /* 這次鎖的是類的Class物件,在鎖Class物件時一切對該類的靜態成員的操作都會上鎖,即當一個執行緒操作這個類的靜態成員時,其他執行緒無法操作這個類的任何靜態成員 @Override public void run() { for (int j = 0; j < 4000; j++) { add(); } } public synchronized static void add(){ i.add(); } */ } class Int{ private int i; public Int(int i) { this.i = i; } public int get() { return i; } public void add() { i++; } }